为什么 WPF 网格对行和列使用附加属性?

Gig*_*igi 1 .net wpf

在 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>
Run Code Online (Sandbox Code Playgroud)

...然后使用附加Grid.RowGrid.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" />
Run Code Online (Sandbox Code Playgroud)

这至少会产生我能想到的两个问题:

  1. 如果我有一堆行并且想在第一行之后插入一些东西,那么我需要Grid.Row从第二行开始为所有项目重新分配。
  2. 如果我决定隐藏一行(例如,基于用户是否具有特定权限),该行仍将占用相同的空间。

这种使用附加属性显式注释网格中每个元素的位置与 HTML 方法形成对比,其中行和单元格按顺序定义:

<table>
    <tr><td>Name:</td><td>John</td></tr>
    <tr><td>Age:</td><td>15</td></tr>
</table>
Run Code Online (Sandbox Code Playgroud)

在 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>
Run Code Online (Sandbox Code Playgroud)

...并通过...删除一行来删除它:

<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>
Run Code Online (Sandbox Code Playgroud)

我非常清楚 WPF 与 HTML 非常不同。为什么 WPF 设计师采用这种方法?有什么办法可以解决上述问题?

esh*_*ham 5

这确实是一件非常烦人的事情。

在我需要将项目一个一个地堆叠在一起的情况下,我只使用 StackPanel。但如果你真的想要网格功能,有一个非常简洁的解决方案:

自动网格

使用 AutoGrid 允许您定义行数和列数,并且您添加到网格的每个元素都会自动分配一个行和列值:

<AutoGrid RowCount="2" RowHeight="35" Columns="100,auto">
  <Label />
  <TextBox />
  <Label />
  <TextBox />
</AutoGrid>
Run Code Online (Sandbox Code Playgroud)

编辑:

我忘了提到UniformGrid,它与AutoGrid不同,它实际上包含在框架中。