WPF Window - Only allow horizontal resize

后端 未结 8 1093
一生所求
一生所求 2021-01-03 23:02

I want to only allow my WPF window to be resized horizontally. How best can I achieve this?

相关标签:
8条回答
  • 2021-01-03 23:32

    If you set the MinHeight and MaxHeight attributes of the window to the desired height the window will have a fixed height

    0 讨论(0)
  • 2021-01-03 23:34

    It's kind of a pain. Basically you need to set up a hook function to process windows messages. Then you would catch the WM_SIZING (0x0214) message and modify the parameters so that the horizontal dimension could not be changed.

    Pete Brown also has some great info on this topic on his blog.

    0 讨论(0)
  • 2021-01-03 23:37

    You could try databinding to the size of the window, and then setting the size back to the old value whenever the vertical dimension is changed.

    0 讨论(0)
  • 2021-01-03 23:41

    If you want to use the MinHeight and MaxHeight approach but still allow the window to automatically size itself to fit the size of its content:

    To allow automatic content sizing don't use the Loaded event. Use the ContentRendered event instead.

    0 讨论(0)
  • 2021-01-03 23:41

    Building on the answers from User3810621 and others, this can be turned into a reusable behavior which locks in the calculated sizes as min and/or max after the first content render:

    namespace whatever.util.wpf.behaviors
    {
        using System.Windows;
        using System.Windows.Interactivity;
    
        public class LockInitialSize : Behavior<Window>
        {
            protected override void OnAttached()
            {
                base.OnAttached();
                AssociatedObject.ContentRendered += OnContentRendered;
            }
    
            protected override void OnDetaching()
            {
                // possibly detached before ever rendering
                AssociatedObject.ContentRendered -= OnContentRendered;
                base.OnDetaching();
            }
    
            private void OnContentRendered(object s, EventArgs e)
            {
                // Just once
                AssociatedObject.ContentRendered -= OnContentRendered;
    
                if (MinWidth)
                {
                    AssociatedObject.MinWidth = AssociatedObject.ActualWidth;
                }
                /// ... MaxWidth, MinHeight, MaxHeight
            }
    
            #region MinWidth Property
    
            public bool MinWidth
            {
                get => (bool)GetValue(MinWidthProperty);
                set => SetValue(MinWidthProperty, value);
            }
    
            public static readonly DependencyProperty MinWidthProperty =
                DependencyProperty.Register(nameof(MinWidth), typeof(bool), typeof(LockInitialSize));
    
            #endregion
    
            // ... MaxWidth, MinHeight, MaxHeight    
        }
    }
    

    The remaining, repetitive values are trivial and omitted for brevity.

    Usage:

    <Window ...
         xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
         xmlns:behaviors="clr-namespace:whatever.util.wpf.behaviors;assembly=whatever"
         SizeToContent="Height"
         ...>
        <i:Interaction.Behaviors>
            <behaviors:LockInitialSize MinHeight="True" MaxHeight="True" />
        </i:Interaction.Behaviors>
    
    0 讨论(0)
  • 2021-01-03 23:51

    The following solution allows you to leave SizeToContent intact,
    doesn't require Win32 Interop or code behind in your Window:

    It does rely on Reactive Extensions

    In the Package Manager run:

    Install-Package System.Reactive
    

    Then you start by creating a new Behavior:

    public class VerticalResizeWindowBehavior : Behavior<UIElement>
    {
        public static readonly DependencyProperty MinHeightProperty = DependencyProperty.Register("MinHeight", typeof(double), typeof(VerticalResizeWindowBehavior), new PropertyMetadata(600.0));
        public double MinHeight
        {
            get { return (double)GetValue(MinHeightProperty); }
            set { SetValue(MinHeightProperty, value); }
        }
    
        protected override void OnAttached()
        {
            base.OnAttached();
    
            var window = Window.GetWindow(AssociatedObject);
            var mouseDown = Observable.FromEventPattern<MouseButtonEventArgs>(AssociatedObject, "MouseLeftButtonDown")
                                        .Select(e => e.EventArgs.GetPosition(AssociatedObject));
    
            var mouseUp = Observable.FromEventPattern<MouseButtonEventArgs>(AssociatedObject, "MouseLeftButtonUp")
                                    .Select(e => e.EventArgs.GetPosition(AssociatedObject));
    
            var mouseMove = Observable.FromEventPattern<MouseEventArgs>(AssociatedObject, "MouseMove")
                                        .Select(e => e.EventArgs.GetPosition(AssociatedObject));
    
            var q = from start in mouseDown
                    from position in mouseMove.TakeUntil(mouseUp)
                    select new { X = position.X - start.X, Y = position.Y - start.Y };
    
            mouseDown.Subscribe(v => AssociatedObject.CaptureMouse());
            mouseUp.Subscribe(v => AssociatedObject.ReleaseMouseCapture());
    
            q.ObserveOnDispatcher().Subscribe(v =>
            {
                var newHeight = window.Height + v.Y;
                window.Height = newHeight < MinHeight ? MinHeight : newHeight;                
            });
        }
    }
    

    Then you add a UIElement at the bottom of your Window and apply the Behavior:

    <Border Background="Gray" 
            Height="10" 
            Cursor="SizeNS"
            Grid.ColumnSpan="2">
        <i:Interaction.Behaviors>
            <b:VerticalResizeWindowBehavior MinHeight="600"/>
        </i:Interaction.Behaviors>
    </Border>
    

    Set the following Properties on your Window:

    ResizeMode="NoResize"
    SizeToContent="Width"
    

    Note: In this example, the user is allowed to resize Vertically but not Horizontally
    You can easily change the code to allow the opposite, or add properties
    to make it configurable.

    0 讨论(0)
提交回复
热议问题