如何通过测量影响DesiredSize?

时间:2014-04-02 15:24:51

标签: c# wpf

我正在使自定义面板更灵敏地设计我的应用程序。

但有些事情困扰我。在我的MeasureOverride覆盖中,我在面板的所有孩子身上调用了测量值。

我的孩子如下所示:

<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。他想要的尺寸的宽度保持在他的最小值。

根据可用空间,预计不会改变所需的尺寸?

2 个答案:

答案 0 :(得分:0)

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

因此,在网格上调用Measure()将返回一个DesiredSize,它足以适合整个网格的内容。不多也不少。您必须使用“star-sizing”包含至少一个行和列定义,以便扩展到您提供的可用宽度。

答案 1 :(得分:0)

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

在我看来,它在一个包装中反应更好,孩子会尝试适合,然后在包装器尝试将下一个孩子插入同一行,否则换行。

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

对谁感兴趣:

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