wpf 按内容限制窗口大小
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12247277/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Window sizing constraints by content
提问by EFraim
I want the window to respect MinWidth/MinHeightand MaxWidth/MaxHeightspecifications of the content control inside.
我希望窗口尊重MinWidth/MinHeight和MaxWidth/MaxHeight内部内容控件的规范。
Some suggested using SizeToContent, but this only helps to set the initial window size, not the constraints.
有些人建议使用SizeToContent,但这仅有助于设置初始窗口大小,而不是约束。
Others suggested overriding MeasureOverrideand setting window's Min/Max height and width there, but this seems to be somewhat unclean, considering that such a trivial problem should surely have a purely declarative solution.
其他人建议MeasureOverride在那里覆盖和设置窗口的最小/最大高度和宽度,但这似乎有些不干净,考虑到这样一个微不足道的问题肯定应该有一个纯粹的声明性解决方案。
Just to mention another solution which seems reasonable but does notwork (and had been previously mentioned in an answer which got deleted): binding MinWidthof the window to MinWidthof the control does not take into account window decorations.
只是提到另一个似乎合理但不起作用的解决方案(并且之前在被删除的答案中提到过):MinWidth将窗口绑定到MinWidth控件不考虑窗口装饰。
采纳答案by Stipo
If the initial window size is set so that actual content size is not coerced by the content's MinWidth/MinHeight and MaxWidth/MaxHeight in the initial layout pass (for example, by using Window.SizeToContent="WidthAndHeight"), then following equations are true:
如果初始窗口大小设置为使实际内容大小不受初始布局过程中内容的 MinWidth/MinHeight 和 MaxWidth/MaxHeight 强制(例如,通过使用 Window.SizeToContent="WidthAndHeight"),则以下等式为真:
Window.ActualSize - Content.ActualSize =
Window.MinSize - Content.MinSize = Window.MaxSize - Content.MaxSize.
Based on these equations you can derive the following code:
基于这些方程,您可以推导出以下代码:
public MainWindow()
{
InitializeComponent();
this.SizeChanged += OnWindowSizeChanged;
}
private static void OnWindowSizeChanged(object sender, SizeChangedEventArgs e)
{
var window = (Window)sender;
var content = (FrameworkElement)window.Content;
window.MinWidth = window.ActualWidth - content.ActualWidth + content.MinWidth;
window.MaxWidth = window.ActualWidth - content.ActualWidth + content.MaxWidth;
window.MinHeight = window.ActualHeight - content.ActualHeight + content.MinHeight;
window.MaxHeight = window.ActualHeight - content.ActualHeight + content.MaxHeight;
window.SizeChanged -= OnWindowSizeChanged;
}
I do not know how to achieve this efficiently using the pure declarative approach since the code should be ran just once after the initial layout pass.
我不知道如何使用纯声明性方法有效地实现这一点,因为代码应该在初始布局传递后只运行一次。
回答by Chnossos
Some suggested using
SizeToContent, but this only helps to set the initial window size, not the constraints.
有些人建议使用
SizeToContent,但这仅有助于设置初始窗口大小,而不是约束。
I worked around this by setting the MinWidthand MinHeightproperties right afterthe windows was initialized:
我通过在窗口初始化后立即设置MinWidth和MinHeight属性来解决这个问题:
MainWindow.xaml
主窗口.xaml
<Window ... SizeToContent="WidthAndHeight">
...
</Window>
MainWindow.xaml.cs
主窗口.xaml.cs
public MainWindow()
{
InitializeComponent();
SourceInitialized += (s, e) =>
{
MinWidth = ActualWidth;
MinHeight = ActualHeight;
};
}
回答by user1834059
Use Binding markup extension. A binding is wpf's way of saying when this property (source) changes update some other property (target). In this case the Grid's MinWidth property is the Source and your window's MinWidth property is the target.
使用绑定标记扩展。绑定是 wpf 表示此属性(源)更改更新某些其他属性(目标)时的方式。在这种情况下,Grid 的 MinWidth 属性是 Source,而您窗口的 MinWidth 属性是目标。
<Window x:Class="MinMaxValuesOnWindows.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="600" Width="800"
MinWidth="{Binding ElementName=gridy, Path=MinWidth}"
MinHeight="{Binding ElementName=gridy, Path=MinHeight}"
MaxWidth="{Binding ElementName=gridy, Path=MaxWidth}"
MaxHeight="{Binding ElementName=gridy, Path=MaxHeight}">
<Grid Name="gridy" MinHeight="80" MinWidth="80" MaxHeight="300" MaxWidth="300"/>
</Window>
As you mentioned in the topic this does not completely work, but you can use a converter on the binding to add on the window frame's height and width before updating the binding target (might require a PInvoke). Since I doubt the window frame thickness is dynamically changing in your application this can probably just be constant value (not necessarily true if user changes themes).
正如您在主题中提到的,这并不完全有效,但您可以在更新绑定目标之前使用绑定上的转换器来添加窗口框架的高度和宽度(可能需要 PInvoke)。由于我怀疑窗口框架厚度在您的应用程序中是否动态变化,因此这可能只是常量值(如果用户更改主题,则不一定正确)。

