在WPF中,如果我想使用Grid布局,我需要设置行和列定义......
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="100" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!-- Cell data goes here -->
</Grid>
...然后使用附加的Grid.Row
和Grid.Column
属性定义网格中项目的位置:
<TextBlock Text="Name:" Grid.Row="0" Grid.Column="0" />
<TextBox Text="{Binding Path=Name}" Grid.Row="0" Grid.Column="1" />
<TextBlock Text="Age:" Grid.Row="1" Grid.Column="0" />
<TextBox Text="{Binding Path=Age}" Grid.Row="1" Grid.Column="1" />
这至少会产生两个我能想到的问题:
Grid.Row
。使用附加属性显式地注释网格中每个元素的位置与HTML方法形成对比,其中行和单元格是按顺序定义的:
<table>
<tr><td>Name:</td><td>John</td></tr>
<tr><td>Age:</td><td>15</td></tr>
</table>
在HTML中,上面提到的场景很容易解决。您只需插入一行即可插入新行:
<table>
<tr><td>Title:</td><td>Mr.</td></tr> <!-- insert win -->
<tr><td>Name:</td><td>John</td></tr>
<tr><td>Age:</td><td>15</td></tr>
</table>
...并删除一行......删除它:
<table>
<tr><td>Title:</td><td>Mr.</td></tr> <!-- insert win -->
<tr><td>Name:</td><td>John</td></tr>
<!-- no more age! and it doesn't take up space any more either -->
</table>
我非常清楚WPF与HTML非常不同。为什么WPF设计师采用这种方法?有没有办法解决上述问题?
答案 0 :(得分:4)
这确实是非常烦人的事情。
在场景中,我需要将项目堆叠在另一个之下,我只使用StackPanel。 但是如果你真的想要网格功能,那就有一个非常简洁的解决方案:
使用AutoGrid可以定义行数和列数,并且为网格添加的每个元素都会自动分配行和列值:
<AutoGrid RowCount="2" RowHeight="35" Columns="100,auto">
<Label />
<TextBox />
<Label />
<TextBox />
</AutoGrid>
修改强>
我忘了提及UniformGrid,与AutoGrid不同,它实际上包含在框架中。
答案 1 :(得分:3)
它只是权力权衡的另一个例子,用于更多规范。您可以更多地控制WPF中的网格,但代价是必须指定更多属性。您不需要在HTML中指定尽可能多的内容,因为它会假设您将如何使用该标记 - 这可能是好的也可能是坏的。如果我不希望我的所有行默认具有相同的高度怎么办?用HTML声明星形符号要困难多少?&#34;
然而,我并不认为它和你想象的那样不同。为了动态隐藏该HTML
在行中,您必须将display
设置为none
,在WPF中,您必须将Visibility
设置为Collapsed
并更改RowDefinition
& #39; s Height
。
设计师采用这种方法的原因是它确实允许更大的灵活性 - Grid
主要是布局管理器,而不是表格显示。附加的属性方法(再次,以必须指定更多属性为代价)提供了更多的控制,这对于布局管理器来说很重要(尽管是的,如果你曾经做过GUI,它们有时会很痛苦。 )。
此外,为了向网格动态添加行以显示数据,您可能不会使用Grid
,而是DataGrid
。您也可以使用UniformGrid
,它类似于HTML的表格(尽管这仍然是一个布局管理器)。还有一个Table
类。