WPF之依赖属性

在学习WPF的过程中,依赖属性(有些教程称之为“依赖项属性,我喜欢称之为”依赖属性)的概念一直搞不明白,实在不明白微软为何要引入这么个难懂的东西。

然后翻书,逛帖子,看源码,总算弄懂了一点了。

先贴出资源吧:

微软DotNet源码(官方的哦,不是我反编译的):Reference Source (microsoft.com)

东邪西毒的博客:继续聊WPF——依赖项属性(1)

                            继续聊WPF——依赖项属性(2)

                            继续聊WPF——依赖项属性(3)

以下是我自己写的,作个笔记:

依赖属性的形式:

// 这里只使用三个参数,实际上可以有五个参数
public static readonly DependencyProperty MarginProperty = DependencyProperty.Register("Margin", typeof(Thickness), _typeofThis);

// 以传统属性的形式,包装依赖属性(MarginProperty),在外部代码看来,它就是个普通的属性。
public Thickness Margin                 
    {
        get { return (Thickness) GetValue(MarginProperty); }

        set { SetValue(MarginProperty, value); }
    }

依赖属性的类型是DependencyProperty,在这个类中,有两个关键的成员:

        public int GlobalIndex{get;} 

        private static Hashtable PropertyFromName;

GlobalIndex:是一个只读的实例属性,作为DependencyProperty对象的全局的且唯一的标识。

PropertyFromName:是一个静态的Hashtable。因此,在DependencyProperty类载入内存的时候,就会创建全局的,唯一的对象(PropertyFromName)。它类似于Dictionary,是一个键值对。key,使用”属性名“ 和”ownerType”的hash值计算而来,value就是依赖属性的对象。因此,PropertyFromName,只是用来保存程序集中所有的依赖随性对象。

       备注:依赖属性的类型是DependencyProperty。实际上它只是包装了真实的数据类型。比如Margin属性的真实类型是Thickness结构,这在注册属性的时候需要指明。因此在设置值时,可以使用真实的数据类型,或者派生的数据类型。

所有的控件、元素,均继承自DependencyObject。它有一个关键字段:

        private EffectiveValueEntry[] _effectiveValues

EffectiveValueEntry类型,有三个字段:

        Value  ——  它表示依赖属性的对象(object类型)

        PropertyIndex    ——  它标识依赖属性的索引,它的值就是DependencyProperty对象的GlobalIndex。

        FullValueSource  ——  它表示依赖属性值的来源。因为属性值可以是本地设置的,也可以是继承自父级元素的,也可以是来自动画、模板、样式的。

由此可见,EffectiveValues采用索引——值的形式,保存的是依赖属性的设置的值。所以他们的关系是:

 

所以,依赖属性的工作方式如下:

  1. DependencyProperty类载入内存,并创建PropertyFromName对象(HashTable)。
  2. 创建依赖属性,并注册。此时DependencyProperty的静态字段PropertyFromName便保存了所有依赖属性的原始值(默认值)
  3. 初始化DependencyObject对象(如控件、元素等),并创建数组EffectiveValueEntry空数组(此步操作用xaml语言完成,该数组由对象持有);
  4. 读取属性值(使用DependencyObject的GetValue() 方法):首先查找本地,如果没有,就找出继承,动画、样式等,都没有找到,就到PropertyFromName中查找默认值
  5. 设置值(使用DependencyObject的SetValue() 方法,将值保存在EffectiveValueEntry数组中。

为何要如此设计:

我的理解:

  1. 可以减少内存消耗。如果使用实例属性,则每个对象都会初始化N个属性,但是这些属性并不一定都使用,则空值属性占用了很多内存。依赖属性,以静态字段的方式,保存默认值,以“依赖”的方式,获得属性值,只有在明确设定属性值时才在EffectiveValueEntry数组中添加索引——属性值的映射,因此可以减少内存的占用。
  2. 根据不同的环境,获取最合适的值。因为WPF应用了样式、模板、动画等功能,这些都可以改变属性的值。如果使用传统属性,则这些操作都要去设置属性的值,系统消耗比较大。而以依赖属性的方式,则只有在明确设置、读取属性值的时候,才会操作属性,如此可以降低系统开销。

 

  • 0
    点赞
  • 0
    收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论

打赏作者

raynadofan

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值