零起点学习WPF之《WPF揭秘》读书笔记(9)——第三章 多个提供程序的支持
3.2.4 多个提供程序的支持
通过以下的5步流程,WPF运行每一个依赖属性并最终计算它们的值。这多亏了依赖属性中内嵌的变更通知才,这个5个流程才能够自动发生。
判断基础值 |
计算(如果有表达式的话) |
应用动画 |
限制(Coerce) |
验证 |
1、判断基础值
大多数属性值提供程序会把基础值的计算机纳入考虑范畴。下面的代码清单显示8个提供程序,他们可以设置大多数依赖属性的值,优先级从高到底依次为:
(1)本地值 (2)样式触发器(3)模板触发器(4)样式设置程序
(5)主题样式触发器(6)主题样式设置程序(7)属性值继承(8)默认值
你已经见到了一些属性值提供程序,如:属性值继承。
本地值:技术上的含义是任何对DependencyObject.SetValue的调用,但是它通常有一个简单的属性赋值,这是用XAML或者是过程式代码完成的。
默认值:默认值指的是属性注册的时候使用的初始值,自然其优先级最低。
2、计算
如果第一步中的值是表达式(派生自System.Windows.Expression的一个对象),那么WPF会执行一种特殊演算步骤——把表达式转换成具体的值。在WPF3.0中表达式尽在使用动态资源或者是数据绑定的时候起作用。
3、应用动画
如果一个或者多个动画正在运行,他们有能力改变改变当前的属性值(使用第二步计算出来的值作为输入)或者是完全替代当前的属性值。因此、动画胜过其他属性值提供程序——就连本地值都不是它的对手。
4、限制(Coerce)
在所有属性值提供程序处理过之后,WPF将拿到几乎是最终值的属性值,如果依赖属性已经注册CoerceValueCallBack委托,还会把 最终的属性值传给 CoerceValueCallBack 委托,该回调函数负责返回一个新值,它是基于自定义逻辑实现的。
例如:内建的WPF控件,像ProgressBar,使用这个回调函数来限制一个叫Value的属性,这个值大于Mininum常数,小于Maxinum常数。如果输入的值小于Mininum,则返回Mininum ,如果大于Maninum则返回Maxinum.
5、验证
最后、如果属性值注册了ValidataValueCallBack之前的限制中的值将被传入ValidataCallBack委托,如果输入的值有效则返回true,否则返回false。返回false 将导致抛出一个异常,并使这个流程都被取消。
【提示】如果没有办法判断当前的属性值来自那里,可以使用DependencyPropertyHelper.GetValueSource方法作为调试助手,它返回一个ValueSource结构,它包含了BaseValueSource枚举类型(它反映了基础值是从那里来的。IsExpression IsAnimated 和 IsCoerced几个布尔类型属性值。
【清楚本地值LocalValue】
你很有可能需要清楚本地值,并让WPF从下一个最高优先级的提供程序中获得值,然后用这个值来设置属性的最终值。幸运的是,DependencyObject 确实提供了这种机制,可以通过调用ClearValue来实现,在C#中,调用Button.ClearValue方法。
b.ClearValue(Button.ForegroundProperty 是一个 DependencyObject静态成员),在调用ClearValue后重新计算基础值,并把本地值从方程式中删除。
属性触发器可以用激活和未激活状态。