Freigeben über


Eigenschaftswertvererbung (WPF .NET)

Die Eigenschaftswertvererbung ist eine Funktion des Windows Presentation Foundation (WPF)-Eigenschaftensystems und gilt für Abhängigkeitseigenschaften. Durch die Vererbung von Eigenschaftswerten können untergeordnete Elemente in einer Elementstruktur den Wert einer bestimmten Eigenschaft vom nächstgelegenen übergeordneten Element ableiten. Da ein übergeordnetes Element möglicherweise auch seinen Eigenschaftswert über die Eigenschaftswertvererbung erhalten hat, geht das System möglicherweise bis zum Seitenanfang zurück.

Das WPF-Eigenschaftensystem aktiviert die Eigenschaftswertvererbung standardmäßig nicht, und die Wertvererbung ist inaktiv, es sei denn, sie ist speziell in den Metadaten der Abhängigkeitseigenschaft aktiviert. Selbst wenn die Eigenschaftswertvererbung aktiviert ist, erbt ein untergeordnetes Element nur einen Eigenschaftswert, wenn kein höherer Rangfolge Wert vorhanden ist.

Voraussetzungen

In diesem Artikel wird ein grundlegendes Wissen über Abhängigkeitseigenschaften vorausgesetzt; außerdem sollten Sie die Übersicht über Abhängigkeitseigenschaftengelesen haben. Um den Beispielen in diesem Artikel zu folgen, hilft es Ihnen, wenn Sie mit Extensible Application Markup Language (XAML) vertraut sind und wissen, wie WPF-Anwendungen geschrieben werden.

Vererbung durch einen Elementbaum

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

Die Vererbung von Eigenschaftswerten ist der Mechanismus, durch den ein Wert einer Abhängigkeitseigenschaft von übergeordneten Elementen zu untergeordneten Elementen innerhalb einer Struktur aus Elementen, die die Eigenschaft enthalten, weitergegeben wird. In XAML-Markup ist ein Baum 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 Eigenschaftsmetadaten Metadaten-, die den Eigenschaftswert Vererbung ermöglicht und den Standardwert auf falsefestlegt. Die AllowDrop Abhängigkeitseigenschaft ist für Canvas, StackPanelund Label Elemente vorhanden, da sie alle von UIElementabgeleitet sind. Da die AllowDrop Abhängigkeitseigenschaft für canvas1 auf truefestgelegt ist, erben die untergeordneten stackPanel1 und label1 Elemente true als AllowDrop Wert.

<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 elementobjekte zur untergeordneten Elementauflistung eines anderen Elementobjekts hinzufügen. Zur Laufzeit wirkt die Eigenschaftswertvererbung auf den resultierenden Objektbaum. Im folgenden Beispiel wird stackPanel2 zur -Kindersammlung von canvas2hinzugefügt. Ebenso wird label2 der untergeordneten Sammlung von stackPanel2hinzugefügt. Da die Abhängigkeitseigenschaft AllowDrop für canvas2 auf truefestgelegt ist, erben die Elemente stackPanel2 und label2 als untergeordnete Elemente true als ihren AllowDrop-Wert.

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)

Praktische Anwendungen der Vererbung von Eigenschaftswerten

Für bestimmte WPF-Abhängigkeitseigenschaften ist die Wertvererbung standardmäßig aktiviert, z. B. AllowDrop und FlowDirection. In der Regel werden Eigenschaften mit aktivierter Wertvererbung standardmäßig für Basis-UI-Elementklassen implementiert, sodass sie für abgeleitete Klassen vorhanden sind. Da z. B. AllowDrop für die UIElement Basisklasse implementiert wird, ist diese Abhängigkeitseigenschaft auch für jedes Steuerelement vorhanden, das von UIElementabgeleitet wird. WPF ermöglicht die Wertvererbung für Abhängigkeitseigenschaften, bei denen es für einen Benutzer praktisch ist, den Eigenschaftswert einmal für ein übergeordnetes Element festzulegen und diesen Eigenschaftswert an nachfolgende Elemente in der Elementstruktur weiterzugeben.

Das Modell der Eigenschaftswertvererbung weist Eigenschaftswerte zu, sowohl geerbte als auch nicht geerbte, gemäß der Vorrangregel der Abhängigkeitseigenschaft zu. Daher wird der Eigenschaftswert des übergeordneten Elements nur auf ein untergeordnetes Element angewendet, wenn die Eigenschaft des untergeordneten Elements keine höhere Priorität hat, wie z. B. einen lokal festgelegten Wert oder einen Wert, der durch Formatvorlagen, Vorlagen oder Datenbindung abgerufen 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 der Eigenschaft Metadaten von FlowDirectionaktiviert ist, muss ein Wert nur einmal am oberen Rand des Elementbaums einer Seite festgelegt werden. In dem seltenen Fall, dass eine Mischung aus Flussrichtungen für eine Seite vorgesehen ist, kann eine andere Flussrichtung für ein Element in der Baumstruktur festgelegt werden, indem ein lokal definierter Wert zugewiesen wird. Die neue Flussrichtung wird dann an untergeordnete Elemente unterhalb dieser Ebene weitergegeben.

Erstellen einer vererbbaren benutzerdefinierten Eigenschaft

Sie können eine benutzerdefinierte Abhängigkeitseigenschaft vererbbar machen, indem Sie die Inherits-Eigenschaft in einer Instanz von FrameworkPropertyMetadataaktivieren und dann Ihre benutzerdefinierte Abhängigkeitseigenschaft bei dieser Metadateninstanz registrieren. Standardmäßig ist Inherits in FrameworkPropertyMetadataauf false festgelegt. Das Erstellen eines vererbbaren Eigenschaftswerts wirkt sich auf die Leistung aus. Legen Sie daher nur Inherits auf true fest, wenn dieses Feature erforderlich ist.

Wenn Sie eine Abhängigkeitseigenschaft registrieren, bei der Inherits in Metadaten aktiviert ist, verwenden Sie die RegisterAttached-Methode, wie unter 'Registrieren einer angehängten Eigenschaft'beschrieben. Weisen Sie der Eigenschaft außerdem einen Standardwert zu, sodass ein vererbbarer Wert vorhanden ist. Möglicherweise möchten Sie auch einen Eigenschaften-Wrapper mit get- und set-Zugriffsmodifikatoren für den Typ des Besitzers erstellen, ähnlich einer nicht angefügten Abhängigkeitseigenschaft. Auf diese Weise können Sie den Eigenschaftswert mithilfe des Eigenschafts-Wrappers bei einem Besitzer oder abgeleiteten Typ festlegen. Im folgenden Beispiel wird eine Abhängigkeitseigenschaft namens IsTransparenterstellt, bei dem Inherits aktiviert ist und der Standardwert falsebeträgt. Das Beispiel enthält auch einen Eigenschaftenwrapper mit get und set Accessoren.

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 ähneln konzeptuell globalen Eigenschaften. Sie können ihren Wert bei jedem DependencyObject überprüfen und ein gültiges Ergebnis erhalten. Das typische Szenario für angefügte Eigenschaften besteht darin, Eigenschaftswerte für untergeordnete Elemente festzulegen. Dieses Szenario ist effektiver, wenn die betreffende Eigenschaft implizit als angefügte Eigenschaft auf jedem DependencyObject-Element im Baum vorhanden ist.

Erben von Eigenschaftswerten über Baumgrenzen hinweg

Die Eigenschaftsvererbung funktioniert durch Durchlaufen einer Struktur von Elementen. Dieser Baum ist häufig parallel zum logischen Baum. Wenn Sie jedoch ein WPF-Core-Objekt, z. B. ein Brush, in das Markup einschließen, das einen Elementbaum definiert, haben Sie einen diskontinuierlichen logischen Baum erstellt. Eine echte logische Struktur wird nicht konzeptionell durch die Brusherweitert, da die logische Struktur ein Konzept auf WPF-Frameworkebene ist. Sie können die Hilfsmethoden von LogicalTreeHelper verwenden, um den Umfang eines logischen Baumes zu analysieren und anzuzeigen. Die Eigenschaftswertvererbung kann geerbte Werte durch einen nicht zusammenhängenden logischen Baum übergeben, aber nur, wenn die vererbbare Eigenschaft als angefügte Eigenschaft registriert wurde und keine absichtliche Vererbungsblockadegrenze vorhanden ist, z. B. eine Frame.

Anmerkung

Obwohl die Eigenschaftswertvererbung möglicherweise für nicht angefügte Abhängigkeitseigenschaften funktioniert, ist das Vererbungsverhalten für eine nicht angefügte Eigenschaft über bestimmte Elementgrenzen im Laufzeitbaum nicht definiert. Wenn Sie Inherits in Eigenschaftenmetadaten angeben, registrieren Sie Ihre Eigenschaften mithilfe von RegisterAttached.

Siehe auch