附加依赖属性
什么时候用
附加属性是一个依赖属性,可以应用于任何 DependencyObject
,以增强了解属性存在的各种控件或服务的行为。
附加属性的一些用例包括:
- 让父元素迭代其子元素并以某种方式对子元素进行操作。例如,
Grid
控件使用Grid.Row
,Grid.Column
,Grid.RowSpan
和Grid.ColumnSpan
附加属性将元素排列成行和列。 - 使用自定义模板向现有控件添加视觉效果,例如在应用范围内为空文本框添加水印,而无需子类
TextBox
。 - 为部分或全部现有控件提供通用服务或功能,例如
ToolTipService
或FocusManager
。这些通常被称为附加行为。 - 当需要继承可视树时,例如类似于
DataContext
的行为。
这进一步说明了 Grid
用例中发生的事情:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Content="Your Name:" />
<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 来注册在元数据中指定 Inherits 的属性。