附加属性是一种依赖项属性,可以将其应用于任何属性,DependencyObject以增强了解该属性存在的各种控件或服务的行为。
附加属性的一些用例包括:
有一个父元素遍历其子元素并以某种方式作用于子元素。例如,Grid控制使用Grid.Row,Grid.Column,Grid.RowSpan,和Grid.ColumnSpan附加属性来安排元件为行和列。
使用自定义模板向现有控件添加视觉效果,在e.g整个应用范围内的空文本框中添加水印,而无需子类化TextBox。
为某些或所有现有控件(例如ToolTipService或)提供通用服务或功能FocusManager。这些通常称为附加行为。
当需要向下继承时,例如,类似于的行为DataContext。
这进一步说明了Grid用例中正在发生的事情:
<Grid> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition /> </Grid.ColumnDefinitions> <Label Grid.Column="0" Content="你的名字:" /> <TextBox Grid.Column="1" Text="{Binding FirstName}" /> </Grid>
Grid.Column不是Label或都不存在的属性TextBox。而是,Grid控件通过其子元素进行查找,并根据附加属性的值对其进行排列。
我们将继续使用Grid此示例。的定义Grid.Column如下所示,但DependencyPropertyChangedEventHandler为简洁起见,将其排除在外。
public static readonly DependencyProperty RowProperty = DependencyProperty.RegisterAttached("Row", typeof(int), typeof(Grid), new FrameworkPropertyMetadata(0, ...)); public static void SetRow(UIElement element, int value) { if (element == null) throw new ArgumentNullException("element"); element.SetValue(RowProperty, value); } public static int GetRow(UIElement element) { if (element == null) throw new ArgumentNullException("element"); return ((int)element.GetValue(RowProperty)); }
由于附加属性可以附加到各种项目,因此不能将其实现为CLR属性。相反,引入了一对静态方法。
因此,与标准依赖项属性相反,附加属性也可以在不是从派生的类中定义DependencyObject。
适用于常规依赖项属性的命名约定也适用于此:依赖项属性RowProperty具有对应的方法GetRow和SetRow。
如MSDN上所述:
尽管属性值继承似乎适用于非附加的依赖项属性,但未定义通过运行时树中某些元素边界的非附加属性的继承行为。始终使用RegisterAttached在元数据中指定继承的位置注册属性。