3

我知道WindowFrameworkElement实际上)你可以指定 aMinWidthMinHeight。我想知道如何使最小匹配窗口的DesiredSize

换句话说,我想说“您可以根据需要调整此窗口的大小,但不能小于显示其内容所需的最小值。”

例如,假设我有一个简单Window的包含 a DockPanel,其中三个项目垂直排列。为简单起见,我们只讨论高度。

  1. 第一个是 a Rectangle,aHeight为 20,固定在顶部,所以它DesiredSize.Height是 20。

  2. 第二个是 a Label,它的 aMinHeight为 20,固定在底部,但如果有多行文本,高度会增加。(目前只有一个单词,所以DesiredSize.Height也是 20)

  3. 第三项是一个自定义控件ImageViewer,它填充了中间的剩余区域,但它永远不会小于它的内容,加上它的填充。目前图像是 15x15,边距是 2.5,所以它DesiredSize.Height是 20 (2.5 + 15 + 2.5)

综上所述,DesiredSize.HeightStackPanel 的 60 (20 + 20 + 20),而DesiredSize.Height60 Window+ 它自己的 chrome 的高度(假设它也是 20),这似乎给了我一个Window.DesiredSize.Height80 的。这就是我为窗口的 MinHeight 所追求的。

我已经尝试通过 a将 The Window's绑定MinHeight到它(这需要 a来确定返回or相应地),但它没有任何效果。DesiredSize.HeightSizeToDoubleConverterDimensionWidthHeight

这看起来很有希望...

protected override Size MeasureOverride(Size availableSize) {

    var desiredSize = base.MeasureOverride(availableSize);

    MinWidth  = Math.Ceiling(DesiredSize.Width);
    MinHeight = Math.Ceiling(DesiredSize.Height);

    return desiredSize;
}

注意:我倾向于Math.Ceiling在实际中使用,DesiredSize.Height因为它通常是一小部分,并且在与设备像素对齐时布局会被抛出,把事情搞砸。

以上接近于工作,但是如果您还想将其设置为MaxHeight等于它(例如,允许水平尺寸,但不允许垂直尺寸),您会遇到问题。

这种事情在 iOS/macOS 中使用 AutoLayout 很容易,但我不确定如何在 WPF 中执行此操作,甚至以编程方式。我只需要继续猜测什么尺寸看起来最好。

4

1 回答 1

1

这是一个很好的问题。我已经实现了目标,但它并不漂亮。我不推荐这种方法,但它确实做到了它在锡上所说的那样。

裸露的骨骼,名为 DynamicMinumumSize 的项目:

MainWindow.xaml.cs:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        DataContext = new BackingData();
    }
}

public class BackingData
{
    public double StackMinHeight { get; set; }
}

xml:

<Window x:Class="DynamicMinimumSize.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:DynamicMinimumSize"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525" d:DataContext="{d:DesignInstance local:BackingData}" MinHeight="{Binding ElementName=Stack, Path=MinHeight}">
    <Window.Resources>
        <ResourceDictionary>
            <local:ChildMinHeightConverter x:Key="ChildMinHeightConverter" />
        </ResourceDictionary>
    </Window.Resources>
    <StackPanel x:Name="Stack">
        <StackPanel.MinHeight>
            <MultiBinding Converter="{StaticResource ChildMinHeightConverter}" >
                <MultiBinding.Bindings>
                    <Binding Path="StackMinHeight" />
                    <Binding RelativeSource="{RelativeSource Self}"/>
                </MultiBinding.Bindings>
            </MultiBinding>
        </StackPanel.MinHeight>
        <Button MinHeight="53">Min Height 53</Button>
        <Button MinHeight="53">Min Height 53</Button>
        <Button MinHeight="53">Min Height 53</Button>
    </StackPanel>
</Window>

转换器:

public class ChildMinHeightConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        var currentMinHeight = values[0] as double? ?? 0;

        if (values[1] is Panel)
        {
            var parent = values[1] as Panel;
            foreach (var child in parent.Children)
            {
                //Hack: The children won't necessarily be buttons
                currentMinHeight += (child as Button).MinHeight;
            }
        }
        //HACK: +40, I think it's the window toolbar.....
        return currentMinHeight + 40;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

可视化:

在此处输入图像描述

于 2018-08-16T09:38:48.657 回答