【发布时间】:2011-03-07 04:13:15
【问题描述】:
我只想让我的 WPF 窗口水平调整大小。 我怎样才能最好地做到这一点?
【问题讨论】:
-
哇,我认为将 MinHeight、Height 和 MaxHeight 设置为相同的值是可行的,但事实并非如此。很高兴知道。
我只想让我的 WPF 窗口水平调整大小。 我怎样才能最好地做到这一点?
【问题讨论】:
这有点痛苦。基本上你需要设置一个钩子函数来处理windows消息。然后您将捕获WM_SIZING (0x0214) 消息并修改参数以使水平尺寸无法更改。
Pete Brown 在他的博客上也有关于这个主题的一些重要信息。
【讨论】:
您可以尝试将数据绑定到窗口的大小,然后在垂直尺寸发生变化时将大小设置回旧值。
【讨论】:
如果您将窗口的MinHeight 和MaxHeight 属性设置为所需的高度,则窗口将具有固定高度
【讨论】:
如果您想使用MinHeight 和MaxHeight 方法但仍允许窗口自动调整大小以适应其内容的大小:
<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;
}
【讨论】:
TextBox 和 Button 的底部边框被设置后,我不得不将 MinHeight 和 MaxHeight 属性设置为 ContentRendered 事件剪辑在 Grid 中包含在 GroupBox 中。
如果您想使用 MinHeight 和 MaxHeight 方法但仍允许窗口自动调整大小以适应其内容的大小:
要允许自动调整内容大小,请不要使用 Loaded 事件。请改用 ContentRendered 事件。
【讨论】:
如果您有以下要求: * 宽度可以由用户调整(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 事件将不起作用。这并不完美,因为用户仍然可以垂直移动光标,如果快速完成会导致一些闪烁。
【讨论】:
以下解决方案可以让您保持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的大小
您可以轻松更改代码以允许相反的情况,或添加属性
使其可配置。
【讨论】:
基于 User3810621 和其他人的答案,这可以转化为可重用行为,在第一次内容渲染后将计算的大小锁定为最小和/或最大:
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>
【讨论】: