一年前写了一篇.Net3.0里的DependencyProperty(1),没下文了,很对不起大家。是啊,都是一年前的事情了。这一年中发生了很多事情……(略)……,最近终于又有空开始研究WPF了。一年过去,WPF发布了3.5版本,有了许多不大不小的改变,我准备接着去年的进度,继续研习下去,现在就先试着把去年准备写的关于DependencyProperty的东西写完吧。
去年说到要介绍一下DependencyProperty的应用,好的,我们继续。
这一节的内容都摘抄自MSDN^_^,因此详细的资料都可以参考MSDN,我在这里稍微解释一下,主要是为了下一个小节做下铺垫。
我第一次看到这种语法的时候想到了css,类似下面这样代码
在这里,XAML和HTML的区别在于HTML是动态的解释性的而XAML是需要被编译的,是强类型的。你需要记住的是,如果希望使用Setter,那么目标属性必须是DependencyProperty。
I am animated
Storyboard.TargetProperty="Color"
From="Red" To="Green" Duration="0:0:5"
AutoReverse="True" RepeatBehavior="Forever" />
注意ColorAnimation小节,定义了TargetProperty是"Color",然后让Color从"Red"到"Greed"变化,同时设定了其他一些参数。动画过程不多介绍,你需要记住的是,如果你希望对某个属性应用动画,那么这个属性必须是DependencyProperty
也许你觉得没什么,仅仅是一个值的继承而已,但是如果你深入想想,Window包含Fontsize这个属性,Button也有,这很好,但是Grid并没有包含Fontsize属性啊,这个值又是怎么继承到Button上的呢?答案就是利用Dependency Property提供的继承功能。
上面那些功能如果使用DependencyProperty,就不能解决,至少会很复杂,否则Microsoft也不会弄出这么一套东西出来。现在我们来总结一下,DependencyProperty自身到底要实现哪些传统属性无法实现或很难实现的功能(上面的应用是抄MSDN的,DependencyProperty还有些功能上面并没有提到,我一并列在下面)
如果你对.net的属性以及元数据等概念了解比较深,也许你第一反应就是DependencyProperty封装了很多反射功能。是的,不论是"Markup Extension"还是"Setter",还是"Animation",我们仅仅通过XAML或程序中的一些字符串就完成了对属性的访问,这正是反射的特征。由于XAML的需要,或者是WPF team项目经理的需要,WPF team决定在WPF中大量使用反射。要知道,反射一向是C#的“贵族功能”,十分损耗性能,假若所有的属性我们都直接通过反射读取,估计在WPF应用程序在性能上就无法接受了(其实现在WPF应用程序在性能上也不怎么地)。DependencyProperty在底层封装了高效的Hash算法来解决通过字符串获得值的问题,在后面的POST中,我会详细介绍DependencyProperty是如何存储值的。
因此,有了DependencyProperty,我们可以放心的使用"Markup Extension","Setter"等等一系列令人激动的功能了,这影响的功能还不只这些,WPF中实现的数据绑定,动画等等强大功能,都靠这个了。
正如上面Window->Grid->Button的例子,在WPF的逻辑树中,我们将使用DependencyProperty来完成属性的继承。
这可能不太好解释,如果你了解过WPF的layout机制可能会比较容易理解。
WPF中并没有传统窗体重绘的机制,所谓“重绘”,是通过DependencyProperty的自动更新属性值来进行的。
当WPF中某些视觉元素的属性变化时,WPF系统能够通过DependencyProperty自动进行重新的"Measure"来确定自己的尺寸大小是否发生了变化,或者自动"Arrange"来确定是否要重新排列自己子元素的位置,又或者自动"Render"来重新绘制元素的图形。
举个例子,我们通常把绘制Button的背景色代码写在Button控件的OnRender事件中,当一个Button的Background属性值变化时,通过DependencyProperty可以引起一个自动Render的过程,又比如,一个Grid对象的行数属性或者列数属性发生改时,Grid应该能够自动重新排列他的子元素。
DependencyProperty还实现了验证输入值的功能,并且当这些值不满足验证条件时,强制的为属性赋一个满足条件的值。
DependencyProperty实现的另外一个功能是自动的属性改变通知,也就是当某个属性的值发生变化时执行某个函数或是触发某个事件。
其实DependencyProperty的机制完全足以让他提供更多的功能,我不可能把它的功能实现一一罗列出来……因此,放上这最后一点。
这些功能都通过一定的机制被DependencyProperty完美的实现了,当我们需要使用这些功能的时候,我们只需要自定义一个DependencyProperty来实现就行了(很符合Microsoft的一贯风格……惯坏程序员 呵呵)
System.Windows.DependencyProperty,这属于WPF一部分
System.Workflow.ComponentModel.DependencyProperty,这属于WWF一部分
但要注意,WWF中的DependencyProperty虽然和WPF中的用法很像,但他和WPF中的DependencyProperty完全不是一个东西
两者有什么不同呢?这么说吧,两者支持的功能不同,例如WPF的DP支持了Animation,而WWF中的DP支持了ActivityBind,而更加有意思的是两者的实现机制虽然大体类似,但具体的代码实现完全不同!如果你有兴趣,你可以使用Reflactor查看一下这两个不同的DependencyProperty的源码。似乎能看出一些MS内部重构代码的痕迹——一个team写了一些代码,另一个team拿去加入了自己的功能,重构了实现,release了两套代码……并且,相比起来感觉WPF Team的版本比WWF team的版本的DependencyProperty复杂多了……扯远了,打住。。。
所以纠正一下,我上面所说的DependencyProperty,以及之后想继续说的,是System.Windows.DependencyProperty,WPF的一部分,而非什么".net 3.0中的Dependency Property"。
这一篇Post首先抄了不少MSDN,介绍了通过DependencyProperty,WPF得以实现的一些功能。然后,我又试图总结了一下DependencyProperty自身所实现的功能,给大家做个参考吧。发现我还是没有开始介绍WPF DependencyProperty的详细用法,下次一定要写了。
最近在研究WPF做项目,希望和大家多多交流,如果文章中有什么不正确的地方,请大家多多指正~
















