WPF窗口 - 仅允许水平调整大小

时间:2010-06-23 06:29:27

标签: wpf resize window

我想只允许我的WPF窗口水平调整大小。 我怎样才能做到最好?

8 个答案:

答案 0 :(得分:29)

如果您想使用MinHeightMaxHeight方法,但仍允许窗口自动调整大小以适合其内容的大小:

<Window x:Class="MyWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        SizeToContent="WidthAndHeight"
        ResizeMode="CanResize"
        Loaded="window_Loaded">

在代码隐藏中:

private void window_Loaded(object sender, RoutedEventArgs e)
{
    this.MinWidth = this.ActualWidth;
    this.MinHeight = this.ActualHeight;
    this.MaxHeight = this.ActualHeight;
}

答案 1 :(得分:26)

如果您将窗口的MinHeightMaxHeight属性设置为所需的高度,则窗口将具有固定的高度

答案 2 :(得分:3)

这是一种痛苦。基本上你需要设置一个钩子函数来处理windows消息。然后,您将捕获WM_SIZING(0x0214)消息并修改参数,以便无法更改水平维度。

Pete Brown在他的博客上也有关于这个主题的一些很好的信息。

答案 3 :(得分:1)

您可以尝试数据绑定到窗口的大小,然后在更改垂直尺寸时将大小设置回旧值。

答案 4 :(得分:1)

以下解决方案允许您保持SizeToContent完整,
在您的窗口中不需要Win32 Interop或代码:

它确实依赖于Reactive Extensions

Package Manager运行中:

Install-Package System.Reactive

然后,您首先要创建一个新的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;                
        });
    }
}

然后在窗口底部添加UIElement并应用Behavior

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

在您的窗口上设置以下属性:

ResizeMode="NoResize"
SizeToContent="Width"

注意:在此示例中,允许用户调整Vertically但不调整Horizontally的尺寸。 您可以轻松更改代码以允许相反,或添加属性
使其可配置。

答案 5 :(得分:0)

如果您想使用MinHeight和MaxHeight方法,但仍允许窗口自动调整大小以适合其内容的大小:

要允许自动调整内容大小,请不要使用Loaded事件。改为使用ContentRendered事件。

答案 6 :(得分:0)

如果您有以下要求: *宽度可以由用户调整大小(ResizeMode = CanResize) *高度自动调整大小(SizeToContent = Height)

它不会有两个原因: *没有ResizeMode = CanResizeHeight *当用户调整窗口大小时,它会将SizeToContent打包为“手动”

我使用的一个简单的黑客就是不断强制“SizeToContent”恢复到我想要的值。

<Window x:Class="MyWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    SizeToContent="Height"
    ResizeMode="CanResize"
    LayoutUpdated="LayoutUpdated">

private void LayoutUpdated(object sender, EventArgs e)
{
    SizeToContent = SizeToContent.Height;
}

您还可以使用ContentRendered事件。 PropertyChanged事件无效。这并不完美,因为用户仍然可以垂直移动光标,如果快速完成,会导致一些闪烁。

答案 7 :(得分:0)

基于User3810621和其他用户的回答,可以将其转变为可重用的行为,该行为将在第一个内容呈现后将计算出的大小锁定为min和/或max:

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    
    }
}

其余的重复值很小,为简洁起见,省略了它们。

用法:

<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>