今天我们来学习WPF一个比较重要的概念:依赖属性。这里推荐大家看看周永恒大哥的文章,讲的确实很不错。我理解的没那么深入,只能发表一下自己的浅见。提到依赖属性,不得不说我们经常使用的传统的.net属性,大家都比较了解,一般拥有get和set访问器,它只是一个语法糖,在CLR层面上其实是两个方法(传统属性也叫CLR属性)和一个私有的字段,由于实例方法在内存中只有一份,所以属性不会过多增加内存负担。和CLR属性相比,依赖属性有哪些特点呢?首先我们来自定义一个具有IsTransparent的Button。
public class MyButton:Button { //第一步:声明并注册依赖属性,设置默认值为false public static readonly DependencyProperty IsTransparentProperty = DependencyProperty.Register("IsTransparent", typeof(bool), typeof(MyButton), new FrameworkPropertyMetadata(defaultValue: false, propertyChangedCallback: new PropertyChangedCallback(IsTransparentChanged))); //第二步:为依赖属性提供.net包装器 public bool IsTransparent { get { return (bool)GetValue(IsTransparentProperty); } set {SetValue(IsTransparentProperty, value);} } public static void IsTransparentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { //Value Change } }
使用propdp这个Code Snippet可以快速创建一个依赖属性。
这里有一个命名约定,依赖属性的名字要以Property结尾来表明它是一个依赖属性。
声明注册的依赖属性是static readonly类型,保证了唯一性。.net包装器不是必须的。
DependencyProperty类采用了Singleton设计模式设计,由DependencyProperty.Register方法返回一个DependencyProperty实例,该方法有三个重载方法:
// // 摘要: // 使用指定的属性名称、属性类型和所有者类型注册依赖项属性。 // // 参数: // name: // 要注册的依赖项对象的名称。在所有者类型的注册命名空间内,名称必须是唯一的。 // // propertyType: // 属性的类型。 // // ownerType: // 正注册依赖项对象的所有者类型。 // // 返回结果: // 一个依赖项对象标识符,应使用它在您的类中设置 public static readonly 字段的值。然后,在以后使用该标识符引用依赖项对象,用于某些操作,例如以编程方式设置其值,或者获取元数据。 [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] public static DependencyProperty Register(string name, Type propertyType, Type ownerType); // // 摘要: // 使用指定的属性名称、属性类型、所有者类型和属性元数据注册依赖项属性。 // // 参数: // name: // 要注册的依赖项对象的名称。 // // propertyType: // 属性的类型。 // // ownerType: // 正注册依赖项对象的所有者类型。 // // typeMetadata: // 依赖项对象的属性元数据。 // // 返回结果: // 一个依赖项对象标识符,应使用它在您的类中设置 public static readonly 字段的值。然后,在以后使用该标识符引用依赖项对象,用于某些操作,例如以编程方式设置其值,或者获取元数据。 [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] public static DependencyProperty Register(string name, Type propertyType, Type ownerType, PropertyMetadata typeMetadata); // // 摘要: // 使用指定的属性名称、属性类型、所有者类型、属性元数据和属性的值验证回调来注册依赖项属性。 // // 参数: // name: // 要注册的依赖项对象的名称。 // // propertyType: // 属性的类型。 // // ownerType: // 正注册依赖项对象的所有者类型。 // // typeMetadata: // 依赖项对象的属性元数据。 // // validateValueCallback: // 对回调的引用,除了典型的类型验证之外,该引用还应执行依赖项对象值的任何自定义验证。 // // 返回结果: // 一个依赖项对象标识符,应使用它在您的类中设置 public static readonly 字段的值。然后,在以后使用该标识符引用依赖项对象,用于某些操作,例如以编程方式设置其值,或者获取元数据。 public static DependencyProperty Register(string name, Type propertyType, Type ownerType, PropertyMetadata typeMetadata, ValidateValueCallback validateValueCallback);