【问题标题】:Window sizing constraints by content按内容划分的窗口大小限制
【发布时间】:2012-08-28 03:45:21
【问题描述】:

我希望窗口尊重 MinWidth/MinHeightMaxWidth/MaxHeight 内部内容控件的规范。

有些人建议使用SizeToContent,但这仅有助于设置初始窗口大小,而不是约束。

其他人建议覆盖MeasureOverride 并在那里设置窗口的最小/最大高度和宽度,但这似乎有点不干净,考虑到这样一个微不足道的问题肯定应该有一个纯粹的声明性解决方案。

仅提及另一种看似合理但不起作用的解决方案(并且之前已在已删除的答案中提到):将窗口的MinWidth绑定到控件的MinWidth不考虑窗户装饰。

【问题讨论】:

    标签: wpf layout sizetocontent


    【解决方案1】:

    如果设置了初始窗口大小,使得实际内容大小不会被初始布局过程中内容的 MinWidth/MinHeight 和 MaxWidth/MaxHeight 强制(例如,通过使用 Window.SizeToContent="WidthAndHeight"),则遵循等式是正确的:

    Window.ActualSize - Content.ActualSize = 
          Window.MinSize - Content.MinSize = Window.MaxSize - Content.MaxSize.
    

    根据这些等式,您可以推导出以下代码:

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

    我不知道如何使用纯声明式方法有效地实现这一点,因为代码应该在初始布局通过后只运行一次。

    【讨论】:

    • 您知道如果内容的 MinWidth/MinHeight 或 MaxWidth/MaxHeight 发生变化,SizeChanged 是否会被触发?或者我应该单独为这些属性附加绑定?
    • 这绝对有用,我目前正在检查它是否完全解决了我的问题。
    【解决方案2】:

    有些人建议使用SizeToContent,但这仅有助于设置初始窗口大小,而不是约束。

    我通过设置MinWidthMinHeight 属性窗口初始化后解决了这个问题:

    MainWindow.xaml

    <Window ... SizeToContent="WidthAndHeight">
        ...
    </Window>
    

    MainWindow.xaml.cs

    public MainWindow()
    {
        InitializeComponent();
        SourceInitialized += (s, e) =>
        {
            MinWidth = ActualWidth;
            MinHeight = ActualHeight;
        };
    }
    

    【讨论】:

      【解决方案3】:

      使用绑定标记扩展。绑定是 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>
      

      正如您在主题中提到的,这并不完全有效,但您可以在绑定上使用转换器来添加窗口框架的高度和宽度,然后再更新绑定目标(可能需要 PInvoke)。由于我怀疑您的应用程序中的窗框厚度是动态变化的,因此这可能只是一个常数值(如果用户更改主题,则不一定如此)。

      【讨论】:

      • 您所说的在技术上是正确的,但正如我在问题中指出的那样,我面临的主要困难是以独立于主题的方式确定装饰尺寸。另一个答案解决了这部分难题,因此我会接受。
      猜你喜欢
      • 2022-01-16
      • 1970-01-01
      • 1970-01-01
      • 2023-03-27
      • 2018-09-20
      • 1970-01-01
      • 1970-01-01
      • 2019-11-26
      • 2020-02-07
      相关资源
      最近更新 更多