闲话WPF之十一(Dependency属性 [3] )
【支持多个提供对象】
WPT提供了独立的、强大的机制来设置Dependency属性的值。由于支持多个提供对象,如果没有很好的机制来处理这些提供对象,那么Dependency属性的值将是不可预测的、系统也将变得混乱。Dependency属性的值取决于这些提供对象,它们以一定的顺序和优先级排列。
下图说明了WPF在计算Dependency属性最终值的5个步骤:
基本的计算过程是:
确定基础值====>计算值(如果是表达式)===>应用动画====>强制值===>值验证
1、确定基础值
多数的提供对象都会影响基础值,下面以优先级顺序列出了可以设置多数Dependency属性值的八个提供对象:
1、Local Value 2、Style Triggers 3、Template Triggers 4、Style Setters
5、Theme Style Triggers 6、Theme Style Setters 7、Property Value Inheritance 8、Default Value
Local Value技术上表示任何对DependencyObject.SetValue的调用。它的最常见形式就是在XAML或者代码中的属性赋值。因为我们通常用.NET的属性方式封装了对GetValue/SetValue的调用。Regitser注册时指定的默认值位于处理过程的最后一步。关于其它的提供对象,如Style、Template将在以后介绍,敬请关注后续内容。
2、计算值
如果第一步得到的是一个表达式,WPF将计算表达式以得到一个具体的值。在3.0版本的WPF中,只有动态资源或者是数据绑定才可能有表达式。也许将来版本的WPF会支持其它类型的表达式。
3、应用动画
如果当前有一个或者多个动画在运行,它们具有修改当前属性值、或者完全替代它的能力。因此,动画的级别比其它属性提供对象都高,甚至是Local Value,我们必须记住这一点。
4、强制值
在处理完所有的提供对象后,WPF将最终的属性值传递到CoerceValueCallback委派。如果Dependency属性在注册时提供了这样的委派,那么就应该根据自定义逻辑返回一个新的值。比如ProgressBar,当所有提供对象最后所提供的值超出了其定义的最大、最小值范围时,ProgressBar将利用这个CoerceValueCallback委派限制在这个范围之内。
5、值验证
最后,前缀的强制值将传递给ValidateValueCallback委派,如果Dependency属性注册了这个委派。当值有效时委派必须返回True,否则返回False。返回False将抛出异常,终止整个进程。
附加说明:如果我们不知道给定的Dependency属性的值来源于何处,可以调用静态的DependencyPropertyHelper.GetValueSource方法。它作为调试时的辅助工具,有时能给我们提供帮助。方法会返回一个ValueSource结构。ValueSource结构中的属性成员BaseValueSource、IsExpression、IsAnimated、IsCoerced分别表示了前面列出的八个提供对象的相应类型。注意:请不要在最后的发布产品中使用这个方法,因为在将来版本的WPF中可能有不同的行为。只应该将其作为调试工具。