Come eseguire l'override dei metadati per una proprietà di dipendenza (WPF .NET)

Quando si deriva da una classe che definisce una proprietà di dipendenza, si ereditano la proprietà di dipendenza e i relativi metadati. Questo articolo descrive come eseguire l'override dei metadati di una proprietà di dipendenza ereditata chiamando il OverrideMetadata metodo . L'override dei metadati consente di modificare le caratteristiche della proprietà di dipendenza ereditata in modo che corrispondano ai requisiti specifici della sottoclasse.

Importante

La documentazione di Desktop Guide per .NET 7 e .NET 6 è in fase di costruzione.

Background

Una classe che definisce una proprietà di dipendenza può specificare le relative caratteristiche in PropertyMetadata o uno dei relativi tipi derivati, ad esempio FrameworkPropertyMetadata. Una di queste caratteristiche è il valore predefinito di una proprietà di dipendenza. Molte classi che definiscono le proprietà di dipendenza, specificano i metadati delle proprietà durante la registrazione delle proprietà di dipendenza. Quando i metadati non vengono specificati durante la registrazione, il sistema di proprietà WPF assegna un PropertyMetadata oggetto con valori predefiniti. Le classi derivate che ereditano le proprietà di dipendenza tramite l'ereditarietà della classe hanno la possibilità di eseguire l'override dei metadati originali di qualsiasi proprietà di dipendenza. In questo modo, le classi derivate possono modificare in modo selettivo le caratteristiche delle proprietà di dipendenza per soddisfare i requisiti della classe. Quando si chiama OverrideMetadata(Type, PropertyMetadata), una classe derivata specifica il proprio tipo come primo parametro e un'istanza di metadati come secondo parametro.

Una classe derivata che esegue l'override dei metadati in una proprietà di dipendenza deve farlo prima che la proprietà venga utilizzata dal sistema di proprietà. Una proprietà di dipendenza viene inserita in uso quando viene creata un'istanza della classe che registra la proprietà. Per soddisfare questo requisito, la classe derivata deve chiamare OverrideMetadata all'interno del relativo costruttore statico. L'override dei metadati di una proprietà di dipendenza dopo che viene creata un'istanza del tipo di proprietario non genererà eccezioni, ma comporterà comportamenti incoerenti nel sistema di proprietà. Inoltre, un tipo derivato non può eseguire l'override dei metadati di una proprietà di dipendenza più volte e tenta di eseguire questa operazione genererà un'eccezione.

Esempio

Nell'esempio seguente la classe TropicalAquarium derivata esegue l'override dei metadati di una proprietà di dipendenza ereditata dalla classe Aquariumbase . Il tipo di metadati è FrameworkPropertyMetadata, che supporta le caratteristiche del framework WPF correlate all'interfaccia utente, AffectsRenderad esempio . La classe derivata non esegue l'override del flag ereditato AffectsRender , ma aggiorna il valore predefinito di AquariumGraphic nelle istanze della classe derivata.

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

Vedi anche