共用方式為


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

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

背景

定義相依性屬性的類別,可以在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

另請參閱