Vererbung von Eigenschaftswerten (WPF .NET)

Die Vererbung von Eigenschaftswert ist ein Feature des Windows Presentation Foundation -Eigenschaftensystems (WPF) und gilt für Abhängigkeitseigenschaften. Mit der Vererbung von Eigenschafts-Wert können untergeordnete Elemente in einer Struktur von Elementen den Wert einer bestimmten Eigenschaft vom nächsten übergeordneten Element abrufen. Da ein übergeordnetes Element seinen Eigenschaftswert auch durch Vererbung von Eigenschaftswerten erhalten haben könnte, kehrt das System möglicherweise zum Stamm der Seite zurück.

Das WPF-Eigenschaftssystem aktiviert standardmäßig keine Eigenschaftswertvererbung, und die Wertvererbung ist inaktiv, es sei denn, dies ist in Abhängigkeitseigenschaftsmetadaten speziell aktiviert. Selbst bei aktivierter Vererbung des Eigenschaftswerts erbt ein untergeordnetes Element nur einen Eigenschaftswert ohne einen höheren Rangwert .

Wichtig

Der Desktopleitfaden zu .NET 7 und .NET 6 ist in Bearbeitung.

Voraussetzungen

Im Artikel wird davon ausgegangen, dass sie grundlegende Kenntnisse über Abhängigkeitseigenschaften haben und eine Übersicht über Abhängigkeitseigenschaften gelesen haben. Um den Beispielen in diesem Artikel zu folgen, hilft es, wenn Sie mit Extensible Application Markup Language (XAML) vertraut sind und wissen, wie WPF-Anwendungen geschrieben werden.

Vererbung über eine Elementstruktur

Die Vererbung von Eigenschafts-Wert ist nicht das gleiche Konzept wie die Klassenvererbung in der objektorientierten Programmierung, bei der abgeleitete Klassen Basisklassenmitglieder erben. Diese Art der Vererbung ist auch in WPF aktiv, obwohl die geerbten Basisklasseneigenschaften in XAML als Attribute von XAML-Elementen verfügbar gemacht werden, die abgeleitete Klassen darstellen.

Die Vererbung von Eigenschafts-Wert ist der Mechanismus, mit dem ein Abhängigkeitseigenschaftswert von übergeordneten an untergeordnete Elemente innerhalb einer Struktur von Elementen, die die -Eigenschaft enthalten, weiterreicht. Im XAML-Markup ist eine Struktur von Elementen als geschachtelte Elemente sichtbar.

Das folgende Beispiel zeigt geschachtelte Elemente in XAML. WPF registriert die AllowDrop Abhängigkeitseigenschaft für die UIElement Klasse mit Eigenschaftenmetadaten , die die Vererbung von Eigenschaftenwerten ermöglicht und den Standardwert auf false. Die AllowDrop-Abhängigkeitseigenschaft ist auf Canvas-, StackPanel- und Label-Elementen vorhanden, da sie alle von UIElement. Da die AllowDrop-Abhängigkeitseigenschaft canvas1 auf true festgelegt ist, erben die absteigenden stackPanel1-, label1- und true-Elemente als Wert AllowDrop.

<Canvas x:Name="canvas1" Grid.Column="0" Margin="20" Background="Orange" AllowDrop="True">
    <StackPanel Name="stackPanel1" Margin="20" Background="Green">
        <Label Name="label1" Margin="20" Height="40" Width="40" Background="Blue"/>
    </StackPanel>
</Canvas>

Sie können auch programmgesteuert eine Struktur von Elementen erstellen, indem Sie der Auflistung untergeordneter Elemente eines anderen Elementobjekts Elementobjekte hinzufügen. Zur Laufzeit wirkt sich die Vererbung von Eigenschaftswerten auf den resultierenden Objektbaum aus. Im folgenden Beispiel stackPanel2 wird der untergeordneten Auflistung von canvas2. Ebenso wird label2 der untergeordneten Auflistung von stackPanel2 hinzugefügt. Da die AllowDrop-Abhängigkeitseigenschaft canvas2 auf true festgelegt ist, erben die absteigenden stackPanel2-, label2- und true-Elemente als Wert AllowDrop.

Canvas canvas2 = new()
{
    AllowDrop = true
};
StackPanel stackPanel2 = new();
Label label2 = new();
canvas2.Children.Add(stackPanel2);
stackPanel2.Children.Add(label2);
Dim canvas2 As New Canvas With {
    .AllowDrop = True
}
Dim stackPanel2 As New StackPanel()
Dim label2 As New Label()
canvas2.Children.Add(stackPanel2)
stackPanel2.Children.Add(label2)

Vererbung von Eigenschaftswerten in der praktischen Anwendung

Bestimmte WPF-Abhängigkeitseigenschaften verfügen standardmäßig über eine Wertvererbung, z. B. AllowDrop und FlowDirection. In der Regel werden Eigenschaften mit standardmäßig aktivierter Wertvererbung für Basiselementklassen der Benutzeroberfläche implementiert, sodass sie in abgeleiteten Klassen vorhanden sind. Da AllowDrop beispielsweise auf der UIElement-Basisklasse implementiert wird, ist diese Abhängigkeitseigenschaft auch auf jedem von ihnen abgeleiteten Steuerelement UIElement vorhanden. WPF aktiviert die Wertvererbung für Abhängigkeitseigenschaften, für die es für einen Benutzer praktisch ist, den Eigenschaftswert einmal für ein übergeordnetes Element fest zu setzen und diesen Eigenschaftswert an Nachfolgerelemente in der Elementstruktur weiter zu geben.

Das Vererbungsmodell des Eigenschaftswerts weist Eigenschaftenwerte zu, sowohl geerbt als auch uninheritiert, entsprechend der Rangfolge der Abhängigkeitseigenschaft. Daher wird ein Eigenschaftswert des übergeordneten Elements nur auf ein untergeordnetes Element angewendet, wenn die untergeordnete Elementeigenschaft keinen höheren Rangfolgewert hat, z. B. einen lokal festgelegten Wert oder einen Wert, der durch Stile, Vorlagen oder Datenbindungen ermittelt wird.

Die FlowDirection-Abhängigkeitseigenschaft legt die Layoutrichtung von Text- und untergeordneten UI-Elementen innerhalb eines übergeordneten Elements fest. Normalerweise erwarten Sie, dass die Flussrichtung von Text- und UI-Elementen innerhalb einer Seite konsistent ist. Da die Wertvererbung in den EigenschaftenmetadatenFlowDirectionaktiviert ist, muss ein Wert nur einmal am oberen Rand der Elementstruktur für eine Seite festgelegt werden. In dem seltenen Fall, in dem eine Mischung aus Flussrichtungen für eine Seite vorgesehen ist, kann eine andere Flussrichtung für ein Element in der Struktur festgelegt werden, indem ein lokal festgelegter Wert zugewiesen wird. Die neue Flussrichtung wird dann an absteigende Elemente unterhalb dieser Ebene verteilt.

Erstellen einer benutzerdefinierten, vererbbaren Eigenschaft

Sie können eine benutzerdefinierte Abhängigkeitseigenschaft erbbar machen, indem Sie die Inherits-Eigenschaft in einer Instanz von FrameworkPropertyMetadata, und dann Ihre benutzerdefinierte Abhängigkeitseigenschaft mit dieser Metadateninstanz registrieren. Inherits ist standardmäßig auf false in FrameworkPropertyMetadata festgelegt. Das Erstellen eines erbbaren Eigenschaftswerts wirkt sich auf die Leistung aus, sodass nur Inherits auf true festgelegt wird, wenn dieses Feature benötigt wird.

Wenn Sie eine Abhängigkeitseigenschaft Inherits mit aktivierten Metadaten registrieren, verwenden Sie die RegisterAttached Methode wie in Registrieren einer angefügten Eigenschaft beschrieben. Weisen Sie auch dem Eigenschaft einen Standardwert zu, sodass ein vererbbarer Wert vorhanden ist. Möglicherweise möchten Sie auch einen Eigenschaftenumbruch mit get- und set-Zugriffsmethoden für den Besitzertyp erstellen, genauso wie sie für eine nicht angefügte Abhängigkeitseigenschaft wären. Auf diese Weise können Sie den Eigenschaftswert mithilfe des Eigenschaftenumbruchs auf einem Besitzer oder abgeleiteten Typ festlegen. Im folgenden Beispiel wird eine Abhängigkeitseigenschaft namens IsTransparent mit Inherits aktiviertem und einem Standardwert false erstellt. Das Beispiel enthält auch einen Eigenschaftenumbruch mit get- und set-Zugriffsmethoden.

public class Canvas_IsTransparentInheritEnabled : Canvas
{
    // Register an attached dependency property with the specified
    // property name, property type, owner type, and property metadata
    // (default value is 'false' and property value inheritance is enabled).
    public static readonly DependencyProperty IsTransparentProperty =
        DependencyProperty.RegisterAttached(
            name: "IsTransparent",
            propertyType: typeof(bool),
            ownerType: typeof(Canvas_IsTransparentInheritEnabled),
            defaultMetadata: new FrameworkPropertyMetadata(
                defaultValue: false,
                flags: FrameworkPropertyMetadataOptions.Inherits));

    // Declare a get accessor method.
    public static bool GetIsTransparent(Canvas element)
    {
        return (bool)element.GetValue(IsTransparentProperty);
    }

    // Declare a set accessor method.
    public static void SetIsTransparent(Canvas element, bool value)
    {
        element.SetValue(IsTransparentProperty, value);
    }

    // For convenience, declare a property wrapper with get/set accessors.
    public bool IsTransparent
    {
        get => (bool)GetValue(IsTransparentProperty);
        set => SetValue(IsTransparentProperty, value);
    }
}
Public Class Canvas_IsTransparentInheritEnabled
    Inherits Canvas

    ' Register an attached dependency property with the specified
    ' property name, property type, owner type, and property metadata
    ' (default value is 'false' and property value inheritance is enabled).
    Public Shared ReadOnly IsTransparentProperty As DependencyProperty =
        DependencyProperty.RegisterAttached(
            name:="IsTransparent",
            propertyType:=GetType(Boolean),
            ownerType:=GetType(Canvas_IsTransparentInheritEnabled),
            defaultMetadata:=New FrameworkPropertyMetadata(
                defaultValue:=False,
                flags:=FrameworkPropertyMetadataOptions.[Inherits]))

    ' Declare a get accessor method.
    Public Shared Function GetIsTransparent(element As Canvas) As Boolean
        Return element.GetValue(IsTransparentProperty)
    End Function

    ' Declare a set accessor method.
    Public Shared Sub SetIsTransparent(element As Canvas, value As Boolean)
        element.SetValue(IsTransparentProperty, value)
    End Sub

    ' For convenience, declare a property wrapper with get/set accessors.
    Public Property IsTransparent As Boolean
        Get
            Return GetValue(IsTransparentProperty)
        End Get
        Set(value As Boolean)
            SetValue(IsTransparentProperty, value)
        End Set
    End Property
End Class

Angefügte Eigenschaften sind konzeptionell ähnlich wie globale Eigenschaften. Sie können deren Wert für beliebige DependencyObject überprüfen und ein gültiges Ergebnis erhalten. Das typische Szenario für angefügte Eigenschaften ist das Festlegen von Eigenschaftswerten für untergeordnete Elemente, und dieses Szenario ist effektiver, wenn die in Frage stellende Eigenschaft implizit als angefügte Eigenschaft für jedes Element in der Struktur DependencyObject vorhanden ist.

Vererbung von Eigenschaftswerten über Strukturgrenzen hinweg

Vererbung erfolgt durch die Traversierung einer Elementstruktur. Diese Struktur ist häufig parallel zur logischen Struktur. Wenn Sie jedoch ein WPF-Objekt auf Kernebene, z. B. Brush, in das Markup, das eine Elementstruktur definiert, verwenden, haben Sie eine diskontinuierlich logische Struktur erstellt. Eine echte logische Struktur erstreckt sich konzeptionell nicht durch Brush, da die logische Struktur ein Konzept auf WPF-Frameworkebene ist. Sie können die Hilfsmethoden von LogicalTreeHelper verwenden, um den Umfang einer logischen Struktur zu analysieren und zu sehen. Die Vererbung von Eigenschaftswert kann geerbte Werte durch eine diskontinierte logische Struktur übergeben, aber nur, wenn die erbbare Eigenschaft als angefügte Eigenschaft registriert wurde, und es gibt keine absichtliche Vererbungsblockierungsgrenze, z. B. eine Frame.

Hinweis

Obwohl die Vererbung von Eigenschaftswerten bei nicht angefügten Abhängigkeitseigenschaften zu funktionieren scheint, ist das Vererbungsverhalten einer nicht angefügten Eigenschaft über einige Elementgrenzen in der Laufzeitstruktur nicht festgelegt. Wenn Sie in Inherits Eigenschaftenmetadaten angeben, registrieren Sie Ihre Eigenschaften mit RegisterAttached.

Weitere Informationen