2013-05-01 119 views
8

我在看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

如果我将第一个和第三个单元格的Grid.RowSpan调整为+/- 1,并将第二个和第四个单元格的Grid.Row调整为+/- 1以考虑多余的行,我得到以下(正确)结果:

enter image description here

我也得到正确的结果,如果我从小区#3去除足够的元素,因此它可以在一个单一的行渲染,就像这样:

enter image description here

而且奇怪的是,删除一些对象只导致s额外空间的OME应用于

enter image description here

我一直在细胞中的元素#1和#3,和行数的数量瞎搞,但我似乎无法找出一个确凿的模式来解释这种行为。

究竟是什么WPF在幕后进行渲染这个Grid时导致额外的空间出现在单元格3上的Grid.RowSpan

+0

我想说,因为网格的措施不同,但我尝试了所有的堆叠面板,它仍然大小错误的行。 – Paparazzi 2013-05-01 17:41:14

+0

有太多'自动'排高度。 Grid控件在处理行和列跨越方面做得非常好,但是当所有行高设置为“Auto”时,就像解决一个有太多未知数的方程一样。将顶端2行中的1个或两个固定在一个固定的高度会极大地帮助您。 – Stewbob 2013-05-01 19:27:59

+0

@Stewbob我也在'Height =“*”'上留下最后一行进行了测试,并没有什么区别。问题在于确定使用“RowSpan”的单元格的高度,而与“Grid”如何分配额外的垂直空间无关。我已更新我的代码示例以包含一个'*'大小的行以帮助将其清除:) – Rachel 2013-05-01 20:04:24

回答

0

我没有一个完整的答案,为什么.NET做你的第三行错了。
但我争辩说,你要求它做的是不合逻辑的,因为没有理由让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> 
+0

是的,我知道这样的代码是不合逻辑的,并且有避免这种行为的简单方法,例如删除不需要的和未定义的第二行(Grid.Row =“1”),但我很好奇WPF在后台执行什么操作首先决定渲染这种方式,并且只使用特定的RowSpans。我怀疑你是对的,WPF在测量未定义的行时应用了一些不正确的权重,因为元素的数量影响了多少额外空间。我猜我需要拉出反射器才能得到一个明确的答案... – Rachel 2013-05-02 16:30:59

+1

我怀疑它得到的权重是错误的(但没有正确的理由,我可以看到使它的重量)。如果你看到什么看起来是正确的加权,我怀疑增量为0,加权0错误,你没有看到错误的答案。 – Paparazzi 2013-05-02 16:36:55

1

我在my question here碰到这种情况之前,大约额外的空间appearing in a ListView

每笔者从微软的员工得到了响应:

该缺陷涉及的步骤在VSP的Measure算法中,它记住了以前发现的最大尺寸,并且强制所有未来的Measure调用报告至少一样大的尺寸。在你的情况下,VSP是在任何触发器开始触发之前进行初始测量的,所以它计算出所有事件都可见的大小。当触发器触发并折叠按钮时,度量算法会计算正确的(小)尺寸,但会强制再次调整结果。

网格的行为出现类似于我的虚拟化堆栈面板的行为:有些事情正在发生与RowDefinition的措施调用,迫使它记住并始终报告尺寸较大,即使后来就停机这条线越小越好。

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

+2

你链接的帖子非常有趣,我怀疑你是正确的,它是度量调用中的一个错误。我希望你不介意,但我会编辑你的答案一点,以包括你的链接帖子的相关报价。我希望有人会发布一个答案,解释幕后发生的情况,并通过反射器或MSDN代码进行备份,但看起来不会发生这种情况,所以我会按照我的想法授予您赏金代表你的答案是最接近我会得到一个坚实的答案。 – Rachel 2013-05-14 16:09:31

+0

Rachel我认为你只是展示了一个好编辑的价值。兰登书屋,注意! – 2013-05-14 17:14:35

0

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

相关问题