Практическое руководство по переопределению метаданных для свойства зависимостей (WPF .NET)

При наследовании от класса, определяющего свойство зависимостей, наследуется свойство зависимостей и его метаданные. В этой статье описывается переопределение метаданных унаследованного свойства зависимостей путем вызова метода OverrideMetadata. Переопределение метаданных позволяет изменять характеристики унаследованного свойства зависимостей в соответствии с требованиями подкласса.

Важно!

Документация по рабочему столу для .NET 7 и .NET 6 находится в стадии разработки.

Общие сведения

Класс, определяющий свойство зависимостей, может задавать его характеристики в типе PropertyMetadata или одном из его производных типов, например FrameworkPropertyMetadata. Одна из этих характеристик — значение по умолчанию свойства зависимостей. Многие классы, определяющие свойства зависимостей, задают метаданные свойств во время регистрации свойств зависимостей. Если метаданные не указаны во время регистрации, система свойств WPF присваивает объекту PropertyMetadata значения по умолчанию. Производные классы, наследующие свойства зависимостей через наследование классов, могут переопределить исходные метаданные любого свойства зависимостей. Таким образом производные классы могут выборочно изменять характеристики свойства зависимостей в соответствии с требованиями класса. При вызове OverrideMetadata(Type, PropertyMetadata) производный класс задает собственный тип в качестве первого параметра, а экземпляр метаданных — в качестве второго параметра.

Производный класс, который переопределяет метаданные для свойства зависимостей, должен сделать это, прежде чем свойство будет использовано системой свойств. Свойство зависимостей используется при создании экземпляра любого экземпляра класса, регистрирующего свойство. Чтобы обеспечить соответствие этому требованию, производный класс должен вызывать OverrideMetadata в своем статическом конструкторе. Переопределение метаданных свойства зависимостей после создания экземпляра его типа владельца не вызовет исключения, но приведет к несогласованному поведению в системе свойств. Кроме того, производный тип не может переопределить метаданные свойства зависимостей несколько раз, и при попытке сделать это, возникает исключение.

Пример

В следующем примере производный класс TropicalAquarium переопределяет метаданные свойства зависимостей, унаследованного от базового класса Aquarium. Тип метаданных — это тип FrameworkPropertyMetadata, который поддерживает связанные с пользовательским интерфейсом характеристики платформы 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

См. также