注释
此内容由 Pearson Education, Inc. 的许可从 框架设计指南:可重用 .NET 库的约定、习惯和模式(第 2 版)重新打印。 该版于2008年出版,此后该书已于 第三版全面修订。 此页上的一些信息可能已过期。
例如,依赖属性(DP)是一个常规属性,用于将其值存储在属性存储中,而不是将其存储在类型变量(字段)中。
附加的依赖属性是依赖属性的一种,采用静态的 Get 和 Set 方法建模,这些方法表示描述对象与其容器之间关系的“属性”(例如 Button
对象在 Panel
容器上的位置)。
✔️ 如果需要属性来支持 WPF 功能(如样式、触发器、数据绑定、动画、动态资源和继承),请提供依赖属性。
依赖属性设计
在实现依赖项属性时,要从 DependencyObject 或其子类型之一继承。 该类型提供属性存储的高效实现,并自动支持 WPF 数据绑定。
✔️ DO 提供常规 CLR 属性和公共静态只读字段,用于存储每个依赖属性的 System.Windows.DependencyProperty 实例。
✔️ DO 通过调用实例方法 DependencyObject.GetValue 和 DependencyObject.SetValue 实现依赖属性。
✔️ DO 通过用“Property”后缀属性的名称来命名依赖属性静态字段。
❌ 请勿在代码中显式设置依赖项属性的默认值;请改为在元数据中设置它们。
如果显式设置属性默认值,可能会阻止该属性通过某种隐式方式(如样式设置)进行设置。
❌ 请勿将代码放入除标准代码以外的属性访问器中,以访问静态字段。
如果属性是通过隐式方式(如样式设置)设置的,则不会执行该代码,因为样式设置直接使用静态字段。
❌ 请勿使用依赖项属性来存储安全数据。 甚至可以公开访问专用依赖项属性。
附加依赖属性设计
上一节中所述的依赖属性表示声明类型的固有属性;例如,该 Text
属性是声明它的属性 TextButton
。 一种特殊的依赖属性是附加依赖属性。
附加属性的经典示例是 Grid.Column 属性。 该属性表示 Button 的列位置(而不是 Grid 的列位置),但仅在按钮包含在网格中时才相关,因此它由网格“附加”到按钮。
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Button Grid.Column="0">Click</Button>
<Button Grid.Column="1">Clack</Button>
</Grid>
附加属性的定义与常规依赖属性的定义大致类似,不同之处在于访问器由静态 Get 和 Set 方法表示:
public class Grid {
public static int GetColumn(DependencyObject obj) {
return (int)obj.GetValue(ColumnProperty);
}
public static void SetColumn(DependencyObject obj, int value) {
obj.SetValue(ColumnProperty,value);
}
public static readonly DependencyProperty ColumnProperty =
DependencyProperty.RegisterAttached(
"Column",
typeof(int),
typeof(Grid)
);
}
依赖属性验证
属性通常实现所谓的验证。 尝试更改属性的值时,将执行验证逻辑。
遗憾的是,依赖属性访问器不能包含任意验证代码。 相反,需要在属性注册期间指定依赖属性验证逻辑。
❌ 请勿将依赖属性验证逻辑放入属性的访问器中。 而是将验证回调传递给 DependencyProperty.Register
方法。
依赖属性更改通知
❌ 请勿在依赖属性访问器中实现更改通知逻辑。 依赖项属性具有内置的更改通知功能,必须通过向PropertyMetadata提供更改通知回调来使用该功能。
依赖属性值强制
当提供给属性设定器的值在实际修改属性存储器之前被设定器修改时,就会发生属性强制。
❌ 请勿在依赖属性访问器中实现强制逻辑。
依赖属性具有内置的约束功能,并且可以通过向 PropertyMetadata
提供约束回调来使用它。
部分内容 © 2005, 2009 Microsoft 公司。 保留所有权利。