只读依赖项属性Read-Only Dependency Properties

本主题介绍只读依赖属性,包括现有只读依赖属性、创建自定义只读依赖属性的方案和技术。This topic describes read-only dependency properties, including existing read-only dependency properties and the scenarios and techniques for creating a custom read-only dependency property.

系统必备Prerequisites

本主题假定你了解实现依赖属性的基本方案,以及如何将元数据应用于自定义依赖属性。This topic assumes that you understand the basic scenarios of implementing a dependency property, and how metadata is applied to a custom dependency property. 有关上下文,请参阅自定义依赖属性依赖属性元数据See Custom Dependency Properties and Dependency Property Metadata for context.

现有只读依赖属性Existing Read-Only Dependency Properties

Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) 框架中定义的某些依赖属性是只读的。Some of the dependency properties defined in the Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) framework are read-only. 指定只读依赖属性的一般原因如下:这些属性应该用于状态确定,但是有多种因素影响该状态,从用户界面设计的角度看,仅将属性设置为该状态并不能达到预期的效果。The typical reason for specifying a read-only dependency property is that these are properties that should be used for state determination, but where that state is influenced by a multitude of factors, but just setting the property to that state isn't desirable from a user interface design perspective. 例如, 属性IsMouseOver实际上只是从鼠标输入中确定的状态。For example, the property IsMouseOver is really just surfacing state as determined from the mouse input. 任何通过避开实际的鼠标输入以编程方式设置此值的尝试都是不可预期的,并将导致不一致。Any attempt to set this value programmatically by circumventing the true mouse input would be unpredictable and would cause inconsistency.

由于其不可设置性,只读依赖属性不适用于依赖属性通常为其提供一个解决方案(即:数据绑定,直接样式化为某个值、验证、动画和继承)的多种方案。By virtue of not being settable, read-only dependency properties aren't appropriate for many of the scenarios for which dependency properties normally offer a solution (namely: data binding, directly stylable to a value, validation, animation, inheritance). 尽管不可设置,但只读依赖属性仍具有一些由属性系统中的依赖属性支持的其他功能。Despite not being settable, read-only dependency properties still have some of the additional capabilities supported by dependency properties in the property system. 只读依赖属性仍可以用作样式中的属性触发器,这是其他功能中最重要的功能。The most important remaining capability is that the read-only dependency property can still be used as a property trigger in a style. 不能使用正常的公共语言运行时 (CLR) 属性启用触发器;它需要是依赖属性。You can't enable triggers with a normal common language runtime (CLR) property; it needs to be a dependency property. 上述IsMouseOver属性是一种很好的示例, 其中对于定义控件样式可能非常有用, 其中, 一些可见属性 (如) 中复合元素的背景、前景或类似属性当用户将鼠标放在控件的某个已定义区域上时, 控件将更改。The aforementioned IsMouseOver property is a perfect example of a scenario where it might be quite useful to define a style for a control, where some visible property such as a background, foreground, or similar properties of composited elements within the control will change when the user places a mouse over some defined region of your control. 只读依赖属性中的更改还可以由属性系统的固有失效进程检测并报告,这实际上是在内部支持属性触发器功能。Changes in a read-only dependency property can also be detected and reported by the property system's inherent invalidation processes, and this in fact supports the property trigger functionality internally.

创建自定义只读依赖属性Creating Custom Read-Only Dependency Properties

请务必阅读上一节中有关只读依赖属性为何不适用于许多典型依赖属性方案的内容。Make sure to read the section above regarding why read-only dependency properties won't work for many typical dependency-property scenarios. 但是如果有适当的方案,可能需要创建自己的只读依赖属性。But if you have an appropriate scenario, you may wish to create your own read-only dependency property.

创建只读依赖属性的大多数过程与自定义依赖属性实现依赖属性主题中介绍的过程相同。Much of the process of creating a read-only dependency property is the same as is described in the Custom Dependency Properties and Implement a Dependency Property topics. 但有三个重要的差异:There are three important differences:

  • 注册属性时, 请调用RegisterReadOnly方法, 而不是正常Register方法进行属性注册。When registering your property, call the RegisterReadOnly method instead of the normal Register method for property registration.

  • 实现 CLR "包装器" 属性时, 请确保该包装也没有集实现, 这样公开的公共包装的只读状态不会造成不一致。When implementing the CLR "wrapper" property, make sure that the wrapper too doesn't have a set implementation, so that there is no inconsistency in read-only state for the public wrapper you expose.

  • 只读注册返回的对象是DependencyPropertyKey DependencyProperty而不是。The object returned by the read-only registration is DependencyPropertyKey rather than DependencyProperty. 仍应将该字段存储为成员,但通常不将其设置为类型的公共成员。You should still store this field as a member but typically you would not make it a public member of the type.

无论你具有什么专用字段或值,可使用你确定的任何逻辑来完全编写对只读依赖属性的支持。Whatever private field or value you have backing your read-only dependency property can of course be fully writable using whatever logic you decide. 不过, 最初或作为运行时逻辑的一部分设置属性的最直接方法是使用属性系统的 Api, 而不是绕过属性系统并直接设置私有支持字段。However, the most straightforward way to set the property either initially or as part of runtime logic is to use the property system's APIs, rather than circumventing the property system and setting the private backing field directly. 特别是, 有一个接受类型SetValue DependencyPropertyKey为的参数的签名。In particular, there is a signature of SetValue that accepts a parameter of type DependencyPropertyKey. 在应用程序逻辑中以编程方式设置此值的方式和位置将影响你在首次注册依赖DependencyPropertyKey属性时, 如何对创建的设置进行访问。How and where you set this value programmatically within your application logic will affect how you may wish to set access on the DependencyPropertyKey created when you first registered the dependency property. 如果完全在专有类中处理此逻辑,或者如果要求从程序集的其他部分对其进行设置,可以在内部进行设置。If you handle this logic all within the class you could make it private, or if you require it to be set from other portions of the assembly you might set it internal. 一种方法是在SetValue相关事件的类事件处理程序中调用, 该事件通知类实例存储的属性值需要更改。One approach is to call SetValue within a class event handler of a relevant event that informs a class instance that the stored property value needs to be changed. 另一种方法是在注册期间使用成对PropertyChangedCallback的和CoerceValueCallback回调作为这些属性的元数据的一部分来关联依赖属性。Another approach is to tie dependency properties together by using paired PropertyChangedCallback and CoerceValueCallback callbacks as part of those properties' metadata during registration.

DependencyPropertyKey由于是私有的, 而不是由代码之外的属性系统传播的, 因此, 只读依赖项属性确实比读写依赖属性具有更好的设置安全性。Because the DependencyPropertyKey is private, and is not propagated by the property system outside of your code, a read-only dependency property does have better setting security than a read-write dependency property. 对于读写依赖属性,标识字段是显式或隐式公用的,因此该属性可广泛设置。For a read-write dependency property, the identifying field is explicitly or implicitly public and thus the property is widely settable. 有关更多详细信息,请参阅依赖属性的安全性For more specifics, see Dependency Property Security.

请参阅See also