简介:
当你开始用WPF编程的时候,很快就会碰到“依赖属性 ”。它们和一般的.Net属性看起来很相似,但简单概念之后则是更复杂和更强大。
主要的区别在于:平常的.NET属性的值直接读取 于类的一个私有属性,而依赖属性的值则是通过调用继承自DependencyObject的GetValue()方法动态赋值 的。
当你给一个依赖属性赋值时,它不是存储在对象的字段 中,而是在存储在基类DependencyObject提供的一个键-值配对的字典 中。一条记录中的键(Key)就是该属性的名称,而值(Value)则是想要设置的值。
依赖属性的优点:
-
节约内存的使用
在你认为超过90%的用户界面控件的属性通常留其初始值时,为每一个属性存储一个字段将是对内存的巨大的浪费。依赖属性解决了仅仅存储改变了属性的问题。默认值在依赖属性中只存储一次。
-
值继承
当你访问一个依赖属性时要使用一个值解决策略。如果当前没有值需要设置,则依赖属性会遍历整个逻辑树直至它找到一个值。当你在根元素中设置字体大小时,它会应用于所有文本块,除非你重写这个值。
依赖属性有一个内嵌的修改通知机制。当属性的值被改变后,通过在属性元数据注册一个的回调函数就能得到修改的通知。同样也可以用在数据绑定中。
值访问策略
每次访问一个依赖属性,它内部会按照下列的顺序由高到底处理该值。它首先确认自身的值是否可用,如果不可用,则会触发一个自定义的样式触发器……继续直到它找到一个值。最后默认值经常是可用的。
背后的秘密
每一个WPF控件注册了一系列的依赖属性在静态的DependencyProperty类中。他们由一个键值(对每个类都是唯一的)和包含默认值和回调函数的原数据组成。
所有要使用依赖属性(DependecyProperties)的类型都必须由DependencyObject来驱动。这个基类定义了一个键值字典来存储依赖属性的所有值。记录中的键则是依赖属性主要申明的。
当你通过.Net属性包装器访问依赖属性的时候,它在内部会调用一个方法GetValue(DependencyProperty)来访问值。下图详细的解释了该方法使用的值解决策略。 如果当前值是可用的,那么就直接从字典(Dictionary)里读出该值。如果没有值被设定,它将上升到整个逻辑树,寻找一个可继承的值。如果没有找到可继承的值,它将被设置为在属性原数据中定义好的默认值。下面的序列有点简化,但它显示了主要的思想。
创建依赖属性
创建一个依赖属性,需添加一个DepdencyProperty类型的静态字段,并调用DependencyProperty.Register()来创建一个依赖属性的实例。依赖属性一般需要以…Property结尾。这样符合PWF的命名规范。
为了使依赖属性像一般的.Net属性一样被访问,则需要添加一个属性包装器。该包装器除了通过继承自DependencyObject的GetValue()和SetValue()方法,以DependencyProperty作为键值来设置和读取它的值外不做任何事情。
强调:不要在这些属性中添加任何逻辑,因为它们仅仅当在代码中赋值的时候才被调用。而在XAML中可直接调用SetValue方法设定属性 。
如果你使用的是Visual Studio,你可以输入propdp在敲两次tab键来自动创建一个依赖属性。
@H_404_112@ 1 // Dependency Property
2 public static readonly DependencyProperty CurrentTimeProperty =
3 DependencyProperty.Register( " CurrentTime " , typeof (DateTime),
4 typeof (MyClockControl), new FrameworkPropertyMetadata(DateTime.Now));
5
6 // .NET Property wrapper
7 public DateTime CurrentTime
8 {
9 get { return (DateTime)GetValue(CurrentTimeProperty); }
10 set { SetValue(CurrentTimeProperty,value); }
11 }