只读依赖项属性
更新:2007 年 11 月
本主题介绍只读依赖项属性,包括现有的只读依赖项属性和创建自定义只读依赖项属性的方案和方法。
本主题包括下列各节。
- 先决条件
- 现有的只读依赖项属性
- 创建自定义只读依赖项属性
- 相关主题
先决条件
本主题假定您了解实现依赖项属性的基本方案以及如何将元数据应用到自定义依赖项属性。有关上下文,请参见自定义的依赖项属性和依赖项属性元数据。
现有的只读依赖项属性
在 Windows Presentation Foundation (WPF) 框架中定义的某些依赖项属性为只读。通常指定只读依赖项属性的原因是:这些属性应该用于状态确定,但是有多种因素影响该状态,从用户界面设计的角度看,仅将属性设置为该状态并不能达到预期的效果。例如,通过鼠标输入确认,属性 IsMouseOver 实际上仅为表层状态。任何通过避开真正的鼠标输入以编程方式设置此值的尝试都将是不可预期的并将导致产生不一致的情况。
由于不可设置性,只读依赖项属性不适于很多依赖项属性通常为其提供一个解决方案(即:数据绑定,可直接对值、验证、动画和继承样式化)的情形。尽管具有不可设置性,只读依赖项属性仍有一些其他由属性系统中的依赖项属性支持的功能。只读依赖项属性仍可以用作样式中的属性触发器,这是其他功能中最为重要的一个。您无法使用常规的公共语言运行时 (CLR) 属性启用触发器,因为该属性必须是依赖项属性。前面提到的 IsMouseOver 属性是以下情形的一个极好的示例:对于定义一个控件的样式非常有用;当用户将鼠标放置在某些控件的定义的区域上方时,一些诸如背景色、前景色或控件内复合元素的类似属性等可视属性将会发生更改。属性系统固有的失效过程还可以检测并报告只读依赖项属性发生的更改,这实际上是在内部支持属性触发器功能。
创建自定义只读依赖项属性
请确保已阅读上一节中有关只读依赖项属性对很多典型的依赖项属性情形不起作用的原因。如果您有适当的方案,则可能希望创建自己的只读依赖项属性。
创建只读依赖项属性的大部分过程与自定义的依赖项属性和如何:实现依赖项属性主题中介绍的内容相同。其中有三个重要的差异:
注册属性时,调用 RegisterReadOnly 方法而不是常规的 Register 方法进行属性注册。
当实现 CLR“包装”属性时,请确保该包装也没有设置的实现,以使公开的公共包装的只读状态中不存在不一致现象。
只读注册返回的对象是 DependencyPropertyKey,而不是 DependencyProperty。您仍应将此字段作为成员存储,但是通常不将其设置为此类型的公共成员。
当然,无论是用私有字段还是值支持只读依赖项属性,使用任何您决定的逻辑都可以是完全可写的。但是,无论是在初始状态下,还是在作为运行时逻辑的一部分时,设置该属性最简单的方法是使用属性系统的 API,而不是避开该属性系统和直接设置私有支持字段。尤其是当存在接受类型 DependencyPropertyKey 的参数的 SetValue 的签名的情况时更是如此。在应用程序逻辑中以编程方式设置此值的方式和位置都将影响可能希望如何设置首次注册依赖项属性时创建的 DependencyPropertyKey 上的访问。如果在可以使此逻辑变为私有的类中处理它,或者需要在程序集(可以在内部设置该逻辑)的其他部分设置该逻辑,则一种方法是调用关联事件的类事件处理程序内的 SetValue,该关联事件通知类实例:存储的属性值需要进行更改。另一种方法是通过在注册期间将成对的 PropertyChangedCallback 和 CoerceValueCallback 回调用作这些属性元数据的一部分来将依赖项属性关联在一起。
由于 DependencyPropertyKey 是私有的,属性系统不会将其传播到代码外,因此只读依赖项属性相对于读写依赖项属性的确具有更好的设置安全。对于读写依赖项属性,由于标识字段为显式或隐式公开,所以这种属性可广泛设置。有关详细内容,请参见依赖项属性的安全性。