如何通过度量影响所需大小

本文关键字:影响 何通过 度量 | 更新日期: 2023-09-27 17:56:07

我正在使自定义面板更能响应设计我的应用程序。

但是有些事情困扰着我。在我覆盖 MeasureOveroverride 的过程中,我在面板的所有子项上调用 Measure。

我的孩子是像下面这样的网格:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition MinWidth="150" MaxWidth="220"/>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition MinWidth="150" MaxWidth="220"/>
        <ColumnDefinition Width="Auto"/>
    </Grid.ColumnDefinitions>
    <TextBlock Text="Formulaire 1" Grid.ColumnSpan="4" Grid.Column="1" Style="{DynamicResource Heading1}"/>
    <Label Content="Label1" HorizontalAlignment="Left" Grid.Row="1" Grid.Column="1"/>
    <Label Content="Label2" HorizontalAlignment="Left" Grid.Row="2" Grid.Column="1"/>
    <Label Content="Label3" HorizontalAlignment="Left" Grid.Row="3" Grid.Column="1"/>
    <Label Content="Label4" HorizontalAlignment="Left" Grid.Row="4" Grid.Column="1"/>
    <Label Content="Label5" HorizontalAlignment="Left" Grid.Row="5" Grid.Column="1"/>
    <Label Content="Label6" HorizontalAlignment="Left" Grid.Row="1" Grid.Column="3"/>
    <Label Content="Label7" HorizontalAlignment="Left" Grid.Row="2" Grid.Column="3"/>
    <Label Content="Label8" HorizontalAlignment="Left" Grid.Row="3" Grid.Column="3"/>
    <Label Content="Label9" HorizontalAlignment="Left" Grid.Row="4" Grid.Column="3"/>
    <Label Content="Label10" HorizontalAlignment="Left" Grid.Row="5" Grid.Column="3"/>
    <Label Content="Message" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="6" Grid.Column="1" />
    <TextBox Grid.Column="2" Grid.Row="1"/>
    <TextBox Grid.Column="2" Grid.Row="2"/>
    <TextBox Grid.Column="2" Grid.Row="3"/>
    <TextBox Grid.Column="2" Grid.Row="4"/>
    <TextBox Grid.Column="2" Grid.Row="5"/>
    <TextBox Grid.Column="4" Grid.Row="1"/>
    <TextBox Grid.Column="4" Grid.Row="2"/>
    <TextBox Grid.Column="4" Grid.Row="3"/>
    <TextBox Grid.Column="4" Grid.Row="4"/>
    <TextBox Grid.Column="4" Grid.Row="5"/>
    <TextBox Grid.ColumnSpan="3" Grid.Column="2" Grid.Row="6" Height="85" />
</Grid>

此网格的最小期望宽度为 ~407,最大期望宽度为 ~547。 +- 140 基于列的最小和最大宽度。

但是,在调用 Measure 时,其可用宽度(远)优于最大所需宽度。他所需尺寸的宽度保持在最小值。

什么不会根据可用空间改变所需的大小?

如何通过度量影响所需大小

除了具有

最小和最大宽度的两列之外,您已将所有行和列指定为"auto"。"GridLength.Auto"根据以下标准计算宽度(或高度):足以适应内容的最小宽度(或高度)。

因此,在网格上调用 Measure() 将返回一个 DesiredSize,该大小恰好足以适合整个网格的内容。不多也不少。您必须使用"星形大小"至少包含一个行和列定义,才能将其扩展到您提供的可用宽度。

我决定从网格继承并覆盖 MeasureOverride 以采用星形和最小/最大值来计算所需的大小。我的面板工作得更好,它应该没有副作用(至少我还没有注意到)。

在我看来,它在包装面板中的响应也更好,孩子会尝试 fo fit,然后在包装面板之后会尝试在同一行中插入下一个孩子,否则会换行。

我真的不明白为什么这不是默认行为。

对谁感兴趣 :

public class CustomGrid : Grid
{
    protected override System.Windows.Size MeasureOverride(System.Windows.Size constraint)
    {
        //I assume Grid.MeasureOverride return the minimum size as desired size
        Size MinimumDesiredSize = base.MeasureOverride(constraint);
        //The remaining available space provided by the container
        double ConstraintWidthRemaining = constraint.Width - MinimumDesiredSize.Width;
        //The supposed remaining space if we assume than star columns width equals 0, will be calculated later
        double WidthRemaining = ConstraintWidthRemaining;
        //The width used in the remaining available space
        double WidthUsed = 0;
        //The number of column which are star sized
        double StarSum = 0;
        foreach (ColumnDefinition column in ColumnDefinitions.Where(c => c.Width.IsStar))
        {
            StarSum += column.Width.Value;
            WidthRemaining += column.MinWidth;
        }
        foreach (ColumnDefinition column in ColumnDefinitions.Where(c => c.Width.IsStar))
        {
            double Ratio = column.Width.Value / StarSum;
            double ColumnWidth = WidthRemaining * Ratio;
            if (column.MaxWidth != 0.0)
            {
                if (ColumnWidth > column.MinWidth)
                {
                    if (ColumnWidth <= column.MaxWidth)
                    {
                        WidthUsed += ColumnWidth - column.MinWidth;
                    }
                    else
                    {
                        WidthUsed += column.MaxWidth - column.MinWidth;
                    }
                }
            }
            else
            {
                WidthUsed += ColumnWidth - column.MinWidth;
            }
        }
        MinimumDesiredSize.Width += WidthUsed;
        return MinimumDesiredSize;
    }
}