wpf 附加的依赖项属性

示例

何时使用

附加属性是一种依赖项属性,可以将其应用于任何属性,DependencyObject以增强了解该属性存在的各种控件或服务的行为。

附加属性的一些用例包括:

  1. 有一个父元素遍历其子元素并以某种方式作用于子元素。例如,Grid控制使用Grid.Row,Grid.Column,Grid.RowSpan,和Grid.ColumnSpan附加属性来安排元件为行和列。

  2. 使用自定义模板向现有控件添加视觉效果,在e.g整个应用范围内的空文本框中添加水印,而无需子类化TextBox。

  3. 为某些或所有现有控件(例如ToolTipService或)提供通用服务或功能FocusManager。这些通常称为附加行为

  4. 当需要向下继承时,例如,类似于的行为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在元数据中指定继承的位置注册属性。