为什么这个额外的空间出现在网格中?

时间:2013-05-01 16:02:45

标签: wpf grid

我正在查看this question并发现了一些非常奇怪的内容:在某些涉及Grid.RowSpan的情况下,似乎错误地计算了行的高度。

以下是我正在测试的Grid的简单图:

---------------
|   1   |     |
--------|  3  |
|   2   |     |
---------------
|      4      |
---------------

以下是此网格的一些示例代码,用于演示此问题:

<Grid ShowGridLines="True">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>

    <StackPanel Grid.Column="0" Grid.Row="0" Grid.RowSpan="2" Background="Red">
        <Label Content="CELL 1 A"/>
        <Label Content="CELL 1 B"/>
        <Label Content="CELL 1 C"/>
    </StackPanel>

    <Grid Grid.Column="0" Grid.Row="2" Background="CornflowerBlue">
        <Label Content="CELL 2 D"/>
    </Grid>

    <StackPanel Grid.Column="1" Grid.Row="0" Grid.RowSpan="3" Background="Yellow">
        <Label Content="CELL 3 A"/>
        <Label Content="CELL 3 B"/>
        <Label Content="CELL 3 C"/>
        <Label Content="CELL 3 D"/>
    </StackPanel>


    <Grid Grid.Column="0" Grid.Row="3" Grid.ColumnSpan="2" Background="Green">
        <Label Content="CELL 4"/>
    </Grid>
</Grid>

最终结果是第3行(单元格#2和#3)的高度中有很多额外的空间:

enter image description here

如果我将第1和第3个单元格的Grid.RowSpan调整为+/- 1,并将第2个和第4个单元格的Grid.Row调整为+/- 1来计算额外的行,我得到这个(正确的)结果:

enter image description here

如果我从单元格#3中删除了足够多的元素,那么我也会得到正确的结果,因此它可以在一行中渲染,如下所示:

enter image description here

奇怪的是,删除一些对象会导致只应用一些额外的空间

enter image description here

我一直在弄乱单元格#1和#3中的元素数量以及行数,但我似乎无法找出解释这种行为的结论模式。

当渲染此网格时,WPF在幕后做什么,以便在单元格#3上Grid.RowSpan时出现额外空间?

3 个答案:

答案 0 :(得分:1)

我之前遇到过这种情况,如my question here中关于额外空间appearing in a ListView

根据我从微软员工那里得到的回复:

  

该错误涉及VSP测量算法中的一个步骤,该算法记住发现的最大尺寸,并强制所有未来的测量调用报告大小至少一样大。在您的情况下,VSP最初是在触发任何触发器之前测量的,因此它会计算大小,就像所有内容都可见一样。当触发器触发并折叠按钮时,度量算法会计算正确的(小)大小,但会强制结果再次变大。

网格的行为看起来类似于我的虚拟化堆栈面板的行为:RowDefinition的测量调用正在进行,这会强制它记住并始终报告更大的尺寸,即使稍后下线越小越好。

简而言之,您可能在WPF中发现了一个错误,因为有无数的变通方法(将所定义的总行数与所需总数相匹配,重新排列您的网格,以及其他任何......)可能永远不会受到关注。您只能通过打开Microsoft Connect错误并等待其回复来确认或驳斥此问题。

答案 1 :(得分:0)

我没有完整回答为什么.NET会让你的第3行出错 但是我认为你要求它做的是不合逻辑的,因为没有理由让0,0跨越两行。
当共享行时,它们可能不等长,WPF必须为较短的(s)添加长度 在您的情况下,因为您在共享行中共享了行,因此WPF必须应用一些加权并且不能正确执行 如果你没有跨越0 0那么它将与行0列0和行1列0共享额外的额外空间,这对我来说是正确的答案。

<Window x:Class="GridRowSizing.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <Style BasedOn="{StaticResource {x:Type Label}}" TargetType="Label">
            <Setter Property="BorderBrush" Value="Black"/>
            <Setter Property="BorderThickness" Value="1"/>
            <Setter Property="Margin" Value="3"/>
        </Style>
    </Window.Resources>
    <Grid ShowGridLines="True">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <StackPanel Grid.Column="0" Grid.Row="0" Background="Red">
            <Label Content="CELL 1 A"/>
            <Label Content="CELL 1 B"/>
            <Label Content="CELL 1 C" BorderBrush="Black" BorderThickness="2"/>
        </StackPanel>
        <StackPanel  Grid.Column="0" Grid.Row="1" Background="CornflowerBlue">
            <Label Content="CELL 2 D" BorderBrush="Black" BorderThickness="2"/>
            <Label Content="CELL 2 E" BorderBrush="Black" BorderThickness="2"/>
        </StackPanel>
        <StackPanel Grid.Column="1" Grid.Row="0" Grid.RowSpan="2" Background="Yellow">
            <Label Content="CELL 3 A"/>
            <Label Content="CELL 3 B"/>
            <Label Content="CELL 3 C"/>
            <Label Content="CELL 3 D" BorderBrush="Black" BorderThickness="2"/>
            <Label Content="CELL 3 E" BorderBrush="Black" BorderThickness="2"/>
            <Label Content="CELL 3 F" BorderBrush="Black" BorderThickness="2"/>
        </StackPanel>
        <StackPanel Grid.Column="0" Grid.Row="2" Grid.ColumnSpan="2" Background="Green">
            <Label Content="CELL 4"/>
        </StackPanel>
    </Grid>
</Window>

答案 2 :(得分:0)

正如Rob所说,这可能是WPF测量呼叫中的一个错误。所以我不知道你的答案。但是为了探索WPF应用程序的内部工作原理,我使用了Snoop。它是一个很棒的工具,类似于显示HTML元素的浏览器工具,snoop向您展示了WPF表单的布局,嵌套元素,元素属性等。在尝试找出布局问题时,它帮助了我很多。我以为我会提到。