只读依赖项属性 (WPF .NET)

可以使用只读依赖项属性来防止从代码外部设置属性值。 本文讨论现有的只读依赖属性以及创建自定义只读依赖属性的方案和技术。

先决条件

本文假设对依赖属性有一个基本的了解,并且你已阅读 依赖项属性概述。 若要遵循本文中的示例,如果熟悉可扩展应用程序标记语言(XAML),并且知道如何编写 WPF 应用程序,则很有帮助。

现有的只读依赖项属性

只读依赖项属性通常报告状态,不应通过 public 访问器进行修改。 例如,Windows Presentation Foundation (WPF) 框架将 IsMouseOver 属性实现为只读,因为其值只能由鼠标输入确定。 如果 IsMouseOver 允许其他输入,则其值可能与鼠标输入不一致。 虽然不能通过 public 访问器进行设置,但许多现有的只读依赖属性具有由多个输入确定的值。

只读依赖属性的用途

只读依赖属性在几个通常依赖属性提供解决方案的情境中不适用。 不适用的方案包括数据绑定、向值应用样式、验证、动画和继承。 但是,只读依赖属性可用作样式中的属性触发器。 例如,IsMouseOver 通常用于在鼠标悬停于其上时触发控件的背景、前景或其他可见属性的变化。 WPF 属性系统检测和报告只读依赖属性中的更改,从而支持属性触发器功能。 实现集合类型依赖属性时,只读依赖属性也很有用,其中只有集合元素需要可写入,而不是集合对象本身。 有关详细信息,请参阅 集合类型依赖属性

注意

只有依赖属性(而不是常规的公共语言运行时属性)可以用作样式中的属性触发器。

创建自定义只读依赖项属性

在创建只读依赖属性之前,请检查 不适用的情况

创建只读依赖属性的过程在许多方面类似于创建读写依赖属性,这些区别如下:

可以使用所选的任何逻辑来确定只读依赖属性的值。 最初或作为运行时逻辑的一部分设置属性值的建议方法是使用接受类型 DependencyPropertyKey参数的 SetValue 重载。 建议使用 SetValue 来避免绕过属性系统,并直接设置后备字段。

在应用程序中设置只读依赖属性的值的方式和位置将影响分配给存储 DependencyPropertyKey的类成员的访问级别。 如果仅在注册依赖属性的类中设置属性值,则可以使用 private 访问修饰符。 对于依赖属性的值相互影响的情况,可以使用配对 PropertyChangedCallbackCoerceValueCallback 回调来触发值更改。 有关详细信息,请参阅 依赖属性元数据

如果需要从注册它的类外部更改只读依赖属性的值,则可以对 DependencyPropertyKey使用 internal 访问修饰符。 例如,你可以从同一程序集中的事件处理器中调用 SetValue。 下面的示例定义了一个水族馆类,该类调用 RegisterReadOnly 来创建只读依赖属性 FishCountDependencyPropertyKey 被分配给 internal static readonly 字段,以便同一程序集中的代码能够修改该只读依赖属性的值。

public class Aquarium : DependencyObject
{
    // Register a dependency property with the specified property name,
    // property type, owner type, and property metadata.
    // Assign DependencyPropertyKey to a nonpublic field.
    internal static readonly DependencyPropertyKey FishCountPropertyKey =
        DependencyProperty.RegisterReadOnly(
          name: "FishCount",
          propertyType: typeof(int),
          ownerType: typeof(Aquarium),
          typeMetadata: new FrameworkPropertyMetadata());

    // Declare a public get accessor.
    public int FishCount =>
        (int)GetValue(FishCountPropertyKey.DependencyProperty);
}
Public Class Aquarium
    Inherits DependencyObject

    ' Register a dependency property with the specified property name,
    ' property type, owner type, And property metadata.
    ' Assign DependencyPropertyKey to a nonpublic field.
    Friend Shared ReadOnly FishCountPropertyKey As DependencyPropertyKey =
        DependencyProperty.RegisterReadOnly(
            name:="FishCount",
            propertyType:=GetType(Integer),
            ownerType:=GetType(Aquarium),
            typeMetadata:=New FrameworkPropertyMetadata())

    ' Declare a public get accessor.
    Public ReadOnly Property FishCount As Integer
        Get
            Return GetValue(FishCountPropertyKey.DependencyProperty)
        End Get
    End Property

End Class

由于 WPF 属性系统不会在代码外部传播 DependencyPropertyKey,所以只读依赖属性的写入安全性优于读写依赖属性。 如果要限制对引用 DependencyPropertyKey的用户的写入访问,请使用只读依赖属性。

相比之下,无论您为其分配了什么访问修饰符,读写依赖属性的依赖属性标识符仍然可以通过属性系统访问。 有关详细信息,请参阅 依赖属性安全性

另请参阅