为什么WPF使用附加属性来定位网格中的位置?

时间:2011-03-15 16:40:14

标签: wpf xaml attached-properties design-decisions

为什么我们需要“附加属性”?它的概念让我有点烦恼,因为你可以想象设置特定DependencyObject上甚至不存在的属性值(并且它们将被默默地忽略)。它几乎看起来像是一个寻找问题的解决方案 - 为什么不只是做什么,例如HTML确实并且让父元素明确地确定了儿童定位等内容吗?

即代替:

<Grid>
  <Grid.ColumnDefinitions>
    <!-- etc. -->
  </Grid.ColumnDefinitions>
  <Grid.RowDefinitions>
    <!-- etc. -->
  </Grid.RowDefinitions>
  <SomeElement Grid.Column="0" Grid.Row="0" />
  <!-- etc. -->
</Grid>

为什么不是这样的(相当于HTML中的<tr><td>):

<Grid>
  <Grid.Row>
    <Grid.Column>
      <SomeElement />
    </Grid.Column>
    <!-- etc. -->
  </Grid.Row>
</Grid>

也许网格只是一个不好的例子,附加属性在其他环境中更有意义?或者我可能完全错过了一些东西?

5 个答案:

答案 0 :(得分:6)

您需要附加属性来定位网格中元素的最明显原因是您可以使用绑定:

<Grid.ItemContainerStyle>
   <Style TargetType="ContentPresenter">
      <Setter Property="Grid.Row" Value="{Binding Row}"/>
      <Setter Property="Grid.Column" Value="{Binding Column}"/>
   </Style>
</Grid.ItemContainerStyle>

要在HTML中实现类似的功能,您必须编写代码,以便在行和/或列号更改时显式删除和重新添加元素。

答案 1 :(得分:2)

由Sells和Griffiths引自Programming WPF :(强调我的)

  

显而易见的解决方案是为FrameworkElement这样的基类定义Dock属性 - 所有WPF用户界面元素都派生自FrameworkElement,这样就可以指定任何内容它的码头位置。但是,DockPanel不是唯一的面板类型,因此我们还需要为其他面板的好处添加属性。 这会增加很多混乱。更糟糕的是,它也是不灵活的 - 如果你想设计一个实现一些新布局机制的自定义面板怎么办?可能需要为其子项定义新属性。

     

附加属性解决了这个问题。它们允许一个元素定义可以“附加”到其他元素的属性。 DockPanel定义了可以应用于任何子级的Dock属性。在XAML中,虚线属性语法(DockPanel.Dock)表示正在使用附加属性

答案 2 :(得分:2)

不是真正的答案,但我认为XAML方法在处理大型网格时比HTML方法更容易阅读和更直观。 HTML表格可能会很痛苦。

答案 3 :(得分:2)

这个想法是控件不需要知道所有可能的容器。如果没有附加属性,UIElement将需要公开特定于每种类型容器的属性(RowColumnDockTopLeft ...)。这会使整个系统的灵活性降低,因为新类型的容器不能轻易地为其包含的每个控件“添加”属性。

答案 4 :(得分:0)

如果TextBox具有“行”和“列”等属性,则当它没有直接放在任何面板中时没有任何意义。

因此它们被实现为附加属性。您可以根据需要“附加”它们。如果它在像DockPanel这样的Panel中,那么这些附加的属性将有意义,否则它们将不会。

希望我清除了一些困惑。