依存関係プロパティのメタデータをオーバーライドする方法 (WPF .NET)

依存関係プロパティを定義するクラスから派生させる場合は、依存関係プロパティとそのメタデータを継承します。 この記事では、OverrideMetadata メソッドを呼び出して、継承された依存関係プロパティのメタデータをオーバーライドする方法について説明します。 メタデータをオーバーライドすると、継承された依存関係プロパティの特性をサブクラス固有の要件に合わせて変更できます。

重要

.NET 7 と .NET 6 用のデスクトップ ガイド ドキュメントは作成中です。

バックグラウンド

依存関係プロパティを定義するクラスでは、その特性を PropertyMetadata で、または FrameworkPropertyMetadata などその派生型の 1 つで指定することができます。 これらの特性の 1 つは、依存関係プロパティの既定値です。 依存関係プロパティを定義するクラスの多くでは、依存関係プロパティの登録時にプロパティ メタデータを指定します。 登録中にメタデータが指定されないと、WPF プロパティ システムによって PropertyMetadata オブジェクトには既定値が割り当てられます。 クラスの継承によって依存関係プロパティを継承する派生クラスには、依存関係プロパティの元のメタデータをオーバーライドするオプションがあります。 このように、派生クラスでは、クラスの要件に合うように依存関係プロパティの特性を選択的に変更することができます。 OverrideMetadata(Type, PropertyMetadata) を呼び出す場合、派生クラスでは、最初のパラメーターとして独自の型を指定し、2 番目のパラメーターとしてメタデータ インスタンスを指定します。

依存関係プロパティのメタデータをオーバーライドする派生クラスでは、プロパティ システムによってそのプロパティが使用状態になる前にオーバーライドを行う必要があります。 依存関係プロパティを登録するクラスのインスタンスがインスタンス化されると、そのプロパティは使用状態になります。 この要件は、派生クラスの静的コンストラクター内で OverrideMetadata を呼び出すことで、容易に満たすことができます。 依存関係プロパティのメタデータをその所有者型のインスタンス化を行った後でオーバーライドした場合、例外は発生しませんが、プロパティ システムでの動作に一貫性がなくなります。 また、派生型では依存関係プロパティのメタデータを 2 回以上オーバーライドすることはできません。それを試みると、例外が発生します。

次の例では、基底クラス Aquarium から継承された依存関係プロパティのメタデータが、派生クラス TropicalAquarium によってオーバーライドされます。 メタデータ型は FrameworkPropertyMetadata です。これによって、AffectsRender などの UI 関連の WPF フレームワーク特性がサポートされます。 派生クラスによって、継承された 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

関連項目