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