依赖属性是wpf中一个新的概念,这种属性是当前的类没有自己的属性,但是可以通过Binding获取其他的对象的属性。当然在使用的过程中,依赖属性一般要被包装成CLR属性。
依赖属性在实际编码中是怎样应用的,不是这篇文章的讨论的内容,此篇主要讨论一下依赖属性是怎样实现的。
首先我们看示例代码:此代码是从http://www.silverlightchina.net/html/study/WPF/2011/0405/6659_3.html中截取出来的。大家可以看此文章,感觉讲的还算通俗易懂。
class MyDependencyProperty { internal static Dictionary<object,MyDependencyProperty>RegisteredDps = new Dictionary<object,MyDependencyProperty>(); internal string Name; internal object Value; /**当当前的依赖属性没有被赋值过,那么,GetValue就会缺省从HashCode为索引的哈希表中获取缺省值。 */ internal object HashCode; private static int globalIndex = 0;//所有的属性值的index将都会大于0 /**index是当前注册DependencyProperty中的序号- 实际上是检索当前依赖属性的检索号 */ internal int Index; private MyDependencyProperty(string name,Type propertyName,Type ownerType,object defaultValue) { this.Name = name; this.Value = defaultValue; this.HashCode = name.GetHashCode() ^ ownerType.GetHashCode(); } public static MyDependencyProperty Register(string name,Type propertyType,object defaultValue) { MyDependencyProperty dp = new MyDependencyProperty(name,propertyType,ownerType,defaultValue); globalIndex++; dp.Index = globalIndex; RegisteredDps.Add(dp.HashCode,dp); return dp; } } internal struct EffectiveValueEntry { internal int PropertyIndex { get; set; } internal object Value { get; set; } } class MyDependencyObject { //这个list用来存储设置的依赖属性值,包括这个类的所有的依赖属性,都会在设置后存储在这里 private List<EffectiveValueEntry> _effectiveValues = new List<EffectiveValueEntry>(); public object GetValue(MyDependencyProperty dp) { //在数据结构中查找对应的依赖属性是否在本地有值。 EffectiveValueEntry effectiveValue = _effectiveValues.FirstOrDefault((i) => i.PropertyIndex == dp.Index); if (effectiveValue.PropertyIndex != 0) {//如果获取的元素的PropertyIndex不等于0,说明本地存在这个属性的值 return effectiveValue.Value; } else {//本地不存在就去Dictionary中区查找。 return MyDependencyProperty.RegisteredDps[dp.HashCode].Value; } } public void SetValue(MyDependencyProperty dp,object value) { //在数据结构中查找对应的依赖属性是否在本地有值。 EffectiveValueEntry effectiveValue = _effectiveValues.FirstOrDefault((i) => i.PropertyIndex == dp.Index); if (effectiveValue.PropertyIndex != 0) {//如果获取的元素的PropertyIndex不等于0,说明本地存在这个属性的值 effectiveValue.Value = value; } else {//本地不存在,但是我们进行了Setvalue的调用,所以需要在本地创建一个该属性的数据结构 effectiveValue = new EffectiveValueEntry() { PropertyIndex = dp.Index,Value = value }; _effectiveValues.Add(effectiveValue); } } }代码中有一些注释。此外,在附上一张自己对依赖属性理解的图。从图中可以看出,所有的依赖属性都注册到了DependencyProperty的静态变量Dictionary<object,DependecyProperty>中,其中object来存储注册DependecyProperty的哈希值。在依赖属性中,index是一个很重主要的值,此值是当前依赖属性注册到Dictionary中的序号。而含有依赖属性的对象都是继承依赖对象(DependencyObject)的,在依赖对象(DependencyObject)中,含有一个此类中所有依赖属性的列表,此列表包含着依赖属性的值。而依赖对象(DepedencyObject)的列表和依赖属性(DependencyProperty)唯一的联系点就是Index值。