如何覆寫相依性屬性的中繼資料 (WPF .NET)

當您衍生自訂相依性屬性的類別時,您會繼承相依性屬性及其中繼資料。 本文說明如何藉由呼叫 OverrideMetadata 方法來覆寫繼承之相依性屬性的中繼資料。 覆寫中繼資料可讓您修改繼承之相依性屬性的特性,以符合子類別特定需求。

重要

.NET 7 和 .NET 6 的桌面指南檔正在建置中。

背景

定義相依性屬性的類別可以在 或其中一個衍生型別中 PropertyMetadata 指定其特性,例如 FrameworkPropertyMetadata 。 其中一個特性是相依性屬性的預設值。 許多定義相依性屬性的類別,在相依性屬性註冊期間指定屬性中繼資料。 註冊期間未指定中繼資料時,WPF 屬性系統會 PropertyMetadata 指派具有預設值的物件。 透過類別繼承繼承相依性屬性的衍生類別可以選擇覆寫任何相依性屬性的原始中繼資料。 如此一來,衍生類別就可以選擇性地修改相依性屬性特性,以符合類別需求。 呼叫 OverrideMetadata(Type, PropertyMetadata) 時,衍生類別會將它自己的類型指定為第一個參數,並將中繼資料實例指定為第二個參數。

覆寫相依性屬性中繼資料的衍生類別,必須先這樣做,屬性才會由屬性系統使用。 當註冊屬性的任何類別實例具現化時,就會使用相依性屬性。 為了協助符合這項需求,衍生類別應該在其靜態建構函式內呼叫 OverrideMetadata 。 在具現化相依性屬性的中繼資料之後,覆寫相依性屬性的中繼資料不會引發例外狀況,但會導致屬性系統中的行為不一致。 此外,衍生類型無法覆寫相依性屬性的中繼資料一次以上,而且嘗試這樣做會引發例外狀況。

範例

在下列範例中,衍生類別 TropicalAquarium 會覆寫繼承自基類 Aquarium 的相依性屬性中繼資料。 元資料類型為 FrameworkPropertyMetadata ,其支援 UI 相關的 WPF 架構特性,例如 AffectsRender 。 衍生類別不會覆寫繼承的 AffectsRender 旗標,但它會更新衍生類別實例的預設值 AquariumGraphic

public class Aquarium : DependencyObject
{
    // Register a dependency property with the specified property name,
    // property type, owner type, and property metadata.
    public static readonly DependencyProperty AquariumGraphicProperty =
        DependencyProperty.Register(
          name: "AquariumGraphic",
          propertyType: typeof(Uri),
          ownerType: typeof(Aquarium),
          typeMetadata: new FrameworkPropertyMetadata(
              defaultValue: new Uri("http://www.contoso.com/aquarium-graphic.jpg"),
              flags: FrameworkPropertyMetadataOptions.AffectsRender)
        );

    // Declare a read-write CLR wrapper with get/set accessors.
    public Uri AquariumGraphic
    {
        get => (Uri)GetValue(AquariumGraphicProperty);
        set => SetValue(AquariumGraphicProperty, value);
    }
}
Public Class Aquarium
    Inherits DependencyObject

    ' Register a dependency property with the specified property name,
    ' property type, owner type, and property metadata.
    Public Shared ReadOnly AquariumGraphicProperty As DependencyProperty =
        DependencyProperty.Register(
            name:="AquariumGraphic",
            propertyType:=GetType(Uri),
            ownerType:=GetType(Aquarium),
            typeMetadata:=New FrameworkPropertyMetadata(
                defaultValue:=New Uri("http://www.contoso.com/aquarium-graphic.jpg"),
                flags:=FrameworkPropertyMetadataOptions.AffectsRender))

    ' Declare a read-write CLR wrapper with get/set accessors.
    Public Property AquariumGraphic As Uri
        Get
            Return CType(GetValue(AquariumGraphicProperty), Uri)
        End Get
        Set
            SetValue(AquariumGraphicProperty, Value)
        End Set
    End Property

End Class
public class TropicalAquarium : Aquarium
{
    // Static constructor.
    static TropicalAquarium()
    {
        // Create a new metadata instance with a modified default value.
        FrameworkPropertyMetadata newPropertyMetadata = new(
            defaultValue: new Uri("http://www.contoso.com/tropical-aquarium-graphic.jpg"));

        // Call OverrideMetadata on the dependency property identifier.
        // Pass in the type for which the new metadata will be applied
        // and the new metadata instance.
        AquariumGraphicProperty.OverrideMetadata(
            forType: typeof(TropicalAquarium),
            typeMetadata: newPropertyMetadata);
    }
}
Public Class TropicalAquarium
    Inherits Aquarium

    ' Static constructor.
    Shared Sub New()
        ' Create a new metadata instance with a modified default value.
        Dim newPropertyMetadata As New FrameworkPropertyMetadata(
            defaultValue:=New Uri("http://www.contoso.com/tropical-aquarium-graphic.jpg"))

        ' Call OverrideMetadata on the dependency property identifier.
        ' Pass in the type for which the new metadata will be applied
        ' and the new metadata instance.
        AquariumGraphicProperty.OverrideMetadata(
            forType:=GetType(TropicalAquarium),
            typeMetadata:=newPropertyMetadata)
    End Sub

End Class

另請參閱