今天我们来学习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);
View Code

相关文章: