Übersicht über angefügte Eigenschaften (WPF .NET)

Eine angefügte Eigenschaft ist ein XAML-Konzept (Extensible Application Markup Language). Angefügte Eigenschaften ermöglichen das Festlegen zusätzlicher Eigenschafts-Wert-Paare für jedes von DependencyObject abgeleitete XAML-Element, obwohl das Element diese zusätzlichen Eigenschaften im Objektmodell nicht definiert. Auf die zusätzlichen Eigenschaften kann global zugegriffen werden. Angefügte Eigenschaften werden in der Regel als spezielle Form der Abhängigkeitseigenschaft definiert, die keinen herkömmlichen Eigenschaftenwrapper aufweist.

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 die Beispiele in diesem Artikel zu befolgen, hilft es, wenn Sie mit XAML vertraut sind und wissen, wie Windows Presentation Foundation (WPF)-Anwendungen geschrieben werden.

Warum angefügte Eigenschaften verwendet werden sollen

Angefügte Eigenschaften ermöglichen. in einem untergeordneten Element einen eindeutigen Wert für eine in einem übergeordneten Element definierte Eigenschaft anzugeben. Ein häufiges Szenario ist ein untergeordnetes Element, das angibt, wie es in der Benutzeroberfläche durch das übergeordnete Element gerendert werden soll. DockPanel.Dock ist z. B. eine angefügte Eigenschaft, da sie in untergeordneten Elementen eines DockPanel-Objekts und nicht in dem DockPanel-Objekt selbst festgelegt ist. Die DockPanel-Klasse definiert ein statisches DependencyProperty-Feld mit dem Namen DockProperty und stellt dann GetDock- und SetDock-Methoden als öffentliche Zugriffsmethoden für die angefügte Eigenschaft bereit.

Angefügte Eigenschaften in XAML

In XAML legen Sie angefügte Eigenschaften mithilfe der Syntax <attached property provider type>.<property name> fest, wobei der Anbieter der angefügten Eigenschaft die Klasse ist, die die angefügte Eigenschaft definiert. Im folgenden Beispiel wird gezeigt, wie ein untergeordnetes Element DockPanel den Eigenschaftswert DockPanel.Dock festlegen kann.

<DockPanel>
    <TextBox DockPanel.Dock="Top">Enter text</TextBox>
</DockPanel>

Die Verwendung ähnelt einer statischen Eigenschaft darin, dass Sie auf den Typ verweisen, der die angefügte Eigenschaft besitzt und registriert (z. B. DockPanel), und nicht auf den Instanznamen.

Wenn Sie eine angefügte Eigenschaft mit einem XAML-Attribut angeben, gilt nur die festgelegte Aktion. Sie können einen Eigenschaftswert nicht direkt über XAML abrufen, obwohl einige indirekte Mechanismen zum Vergleichen von Werten vorhanden sind, wie z.B. Trigger in Formaten.

Angefügte Eigenschaften in WPF

Angefügte Eigenschaften sind ein XAML-Konzept, Abhängigkeitseigenschaften sind ein WPF-Konzept sind. In WPF werden die meisten auf die Benutzeroberfläche bezogenen angefügten Eigenschaften für WPF-Typen als Abhängigkeitseigenschaften implementiert. Angefügte WPF-Eigenschaften, die als Abhängigkeitseigenschaften implementiert werden, unterstützen Konzepte von Abhängigkeitseigenschaften, z. B. Eigenschaftsmetadaten, einschließlich Standardwerte aus Metadaten.

Nutzungsmodelle für angefügte Eigenschaften

Obwohl jedes Objekt den Wert einer angefügten Eigenschaft festlegen kann, bedeutet dies nicht, dass das Festlegen eines Werts ein konkretes Ergebnis erzeugt, oder der Wert von einem anderen Objekt verwendet wird. Der Hauptzweck angefügter Eigenschaften besteht darin, Objekten aus einer Vielzahl von Klassenhierarchien und logischen Beziehungen zu ermöglichen, allgemeine Informationen an den Typ zu melden, der die angefügte Eigenschaft definiert. Die Verwendung angefügter Eigenschaften folgt in der Regel einem der folgenden Modelle:

  • Der Typ, der die angefügte Eigenschaft definiert, ist das übergeordnete Element der Elemente, das Werte für die angefügte Eigenschaft festlegt. Der übergeordnete Typ durchläuft seine untergeordneten Objekte durch die interne Logik, die sich auf die Objektstruktur auswirkt, ruft die Werte ab und führt bestimmte Aktionen für diese Werte aus.
  • Der Typ, der die angefügte Eigenschaft definiert, wird als untergeordnetes Element für verschiedene mögliche übergeordnete Elemente und Inhaltsmodelle verwendet.
  • Der Typ, der die angefügte Eigenschaft definiert, stellt einen Dienst dar. Andere Typen legen Werte für die angefügte Eigenschaft fest. Wenn das Element, das die Eigenschaft festlegt, im Kontext des Dienstes ausgewertet wird, werden über die interne Logik der Dienstklasse die angefügten Eigenschaftswerte abgerufen.

Ein Beispiel für eine übergeordnete definierte angefügte Eigenschaft

Das typische Szenario, in dem WPF eine angefügte Eigenschaft definiert: Wenn ein übergeordnetes Element eine Auflistung untergeordneter Elemente unterstützt und ein Verhalten implementiert, das auf den von den einzelnen untergeordneten Elementen gemeldeten Daten basiert.

DockPanel definiert die angefügte DockPanel.Dock-Eigenschaft. DockPanel verfügt über Code auf Klassenebene, insbesondere MeasureOverride und ArrangeOverride, was Teil der Renderinglogik ist. Eine DockPanel-Instanz überprüft, ob eines ihrer unmittelbaren untergeordneten Elemente einen Wert für DockPanel.Dock festgelegt hat. Wenn dies der Fall ist, werden diese Werte Eingaben für die auf das jeweilige untergeordnete Element angewendete Renderinglogik. Obwohl es theoretisch möglich ist, dass angefügte Eigenschaften Elemente außerhalb des unmittelbaren übergeordneten Elements beeinflussen, besteht das definierte Verhalten für eine geschachtelte DockPanel-Instanz darin, nur mit der Sammlung seiner unmittelbaren untergeordneten Elemente zu interagieren. Wenn Sie also DockPanel.Dock für ein Element festlegen, das kein übergeordnetes DockPanel-Element aufweist, werden keine Fehler oder Ausnahmen ausgelöst, und Sie hätten einen globalen Eigenschaftswert erstellt, der von keinem DockPanel-Objekt verwendet wird.

Angefügte Eigenschaften in Code

Angefügte Eigenschaften in WPF verfügen nicht über die typischen CLR-Wrappermethoden get und set, da die Eigenschaften möglicherweise außerhalb des CLR-Namespace festgelegt werden. Damit ein XAML-Prozessor diese Werte beim Analysieren von XAML festlegen kann, muss die Klasse, die die angefügte Eigenschaft definiert, dedizierte Zugriffsmethoden in Form von Get<property name> und Set<property name> implementieren.

Sie können auch die dedizierten Zugriffsmethoden verwenden, um eine angefügte Eigenschaft im Code abzurufen und festzulegen, wie im folgenden Beispiel gezeigt. Im Codebeispiel ist myTextBox eine Instanz der TextBox-Klasse.

DockPanel myDockPanel = new();
TextBox myTextBox = new();
myTextBox.Text = "Enter text";

// Add child element to the DockPanel.
myDockPanel.Children.Add(myTextBox);

// Set the attached property value.
DockPanel.SetDock(myTextBox, Dock.Top);
Dim myDockPanel As DockPanel = New DockPanel()
Dim myTextBox As TextBox = New TextBox()
myTextBox.Text = "Enter text"

' Add child element to the DockPanel.
myDockPanel.Children.Add(myTextBox)

' Set the attached property value.
DockPanel.SetDock(myTextBox, Dock.Top)

Wenn Sie myTextBox nicht als untergeordnetes Element von myDockPanel hinzufügen, löst das Aufrufen von SetDock keine Ausnahme aus und hat keine Auswirkung. Nur ein DockPanel.Dock-Wert, der für ein untergeordnetes Element eines DockPanel-Objekts festgelegt wird, kann sich auf das Rendern auswirken, und das Rendering ist gleich, egal, ob Sie den Wert vor oder nach dem Hinzufügen des untergeordneten Elements zum DockPanel-Objekt festlegen.

Aus Codeperspektive gleicht eine angefügte Eigenschaft einem Unterstützungsfeld, das über method-Zugriffsmethoden anstelle von property-Zugriffsmethoden verfügt und für jedes Objekt festgelegt werden kann, ohne zuvor für diese Objekte definiert werden zu müssen.

Metadaten angefügter Eigenschaften

Metadaten für eine angefügte Eigenschaft unterscheiden sich im Allgemeinen nicht von denen für eine Abhängigkeitseigenschaft. Bei der Registrierung einer angefügten Eigenschaft verwenden Sie FrameworkPropertyMetadata, um die Merkmale der Eigenschaft festzulegen, z. B. ob die Eigenschaft das Rendering oder die Messung beeinflusst. Wenn Sie einen Standardwert durch Überschreiben der Metadaten einer angefügten Eigenschaft festlegen, wird dieser Wert der Standardwert für die implizite angefügte Eigenschaft in Instanzen der überschreibenden Klasse. Ist für eine angefügte Eigenschaft kein anderer Wert festgelegt, wird der Standardwert gemeldet, wenn die Eigenschaft mit der Get<property name>-Zugriffsmethode mit einer Instanz der Klasse abgefragt wird, in der Sie die Metadaten angegeben haben.

Um die Vererbung von Eigenschaftswerten für eine Eigenschaft zu aktivieren, verwenden Sie angefügte Eigenschaften anstelle von nicht angefügten Abhängigkeitseigenschaften. Weitere Informationen finden Sie unter Vererbung von Eigenschaftswerten.

Benutzerdefinierte angefügte Eigenschaften

Wann eine angefügte Eigenschaft erstellt werden soll

In Folgenden Fällen ist es nützlich, eine angefügte Eigenschaft zu erstellen:

  • Sie benötigen einen Mechanismus zum Festlegen von Eigenschaften, der anderen als der definierenden Klasse zur Verfügung steht. Ein häufiges Szenario ist das UI-Layout, so sind DockPanel.Dock, Panel.ZIndex und Canvas.Top etwa Beispiele für vorhandene Layouteigenschaften. Im Layoutszenario können untergeordnete Elemente eines Layoutsteuerungselements Layoutanforderungen an das übergeordnete Layout ausdrücken und einen Wert für eine durch das übergeordnete Element definierte angefügte Eigenschaft festlegen.

  • Eine Ihrer Klassen stellt einen Dienst dar, und Sie möchten, dass andere Klassen den Dienst transparenter integrieren.

  • Sie möchten den WPF-Designer für Visual Studio unterstützen, um z. B. die Möglichkeit zu erhalten, eine Eigenschaft über das Eigenschaften-Fenster zu bearbeiten. Weitere Informationen finden Sie unter Übersicht über das Erstellen von Steuerelementen.

  • Sie möchten die Vererbung von Eigenschaftswerten verwenden.

Erstellen einer angefügten Eigenschaft

Wenn Ihre Klasse eine angefügte Eigenschaft ausschließlich für die Verwendung durch andere Typen definiert, muss Ihre Klasse nicht von DependencyObject abgeleitet werden. Andernfalls folgen Sie dem WPF-Modell, dass eine angefügte Eigenschaft auch eine Abhängigkeitseigenschaft sein muss, indem Ihre Klasse von DependencyObject abgeleitet wird.

Definieren Sie die angefügte Eigenschaft als Abhängigkeit in der definierenden Klasse, indem Sie ein Feld public static readonly des Typs DependencyProperty deklarieren. Weisen Sie dann dem Feld den Rückgabewert der RegisterAttached-Methode zu, der auch als Abhängigkeitseigenschaftsbezeichner bezeichnet wird. Folgen Sie der Benennungskonvention für WPF-Eigenschaften, die Felder von den Eigenschaften unterscheidet, die sie darstellen, indem das Bezeichnerfeld <property name>Property genannt wird. Stellen Sie außerdem statische Get<property name>- und Set<property name>-Zugriffsmethoden bereit, mit denen das Eigenschaftssystem auf Ihre angefügte Eigenschaft zugreifen kann.

Im folgenden Beispiel wird gezeigt, wie Sie eine Abhängigkeitseigenschaft mithilfe der RegisterAttached-Methode registrieren und die Zugriffsmethoden definieren. Im Beispiel lautet der Name der angefügten Eigenschaft HasFish, daher wird das Bezeichnerfeld HasFishProperty genannt, und die Zugriffsmethoden werden GetHasFish und SetHasFish genannt.

public class Aquarium : UIElement
{
    // Register an attached dependency property with the specified
    // property name, property type, owner type, and property metadata.
    public static readonly DependencyProperty HasFishProperty = 
        DependencyProperty.RegisterAttached(
      "HasFish",
      typeof(bool),
      typeof(Aquarium),
      new FrameworkPropertyMetadata(defaultValue: false,
          flags: FrameworkPropertyMetadataOptions.AffectsRender)
    );

    // Declare a get accessor method.
    public static bool GetHasFish(UIElement target) =>
        (bool)target.GetValue(HasFishProperty);

    // Declare a set accessor method.
    public static void SetHasFish(UIElement target, bool value) =>
        target.SetValue(HasFishProperty, value);
}
Public Class Aquarium
    Inherits UIElement

    ' Register an attached dependency property with the specified
    ' property name, property type, owner type, and property metadata.
    Public Shared ReadOnly HasFishProperty As DependencyProperty =
        DependencyProperty.RegisterAttached("HasFish", GetType(Boolean), GetType(Aquarium),
            New FrameworkPropertyMetadata(defaultValue:=False,
                flags:=FrameworkPropertyMetadataOptions.AffectsRender))

    ' Declare a get accessor method.
    Public Shared Function GetHasFish(target As UIElement) As Boolean
        Return target.GetValue(HasFishProperty)
    End Function

    ' Declare a set accessor method.
    Public Shared Sub SetHasFish(target As UIElement, value As Boolean)
        target.SetValue(HasFishProperty, value)
    End Sub

End Class

Die get-Zugriffsmethode

Die get-Zugriffsmethodensignatur ist public static object Get<property name>(DependencyObject target), wobei:

  • target ist das DependencyObject, aus dem die angefügte Eigenschaft gelesen wird. Der target-Typ kann spezifischer sein als DependencyObject. Beispielsweise typisiert die DockPanel.GetDock-Zugriffsmethode das target-Objekt als UIElement, weil die angefügte Eigenschaft für UIElement-Instanzen festgelegt werden soll. UiElement wird indirekt von DependencyObject abgeleitet.
  • Der Rückgabetyp kann spezifischer sein als object. Beispielsweise typisiert die GetDock-Methode den zurückgegebenen Wert als Dock, weil der Rückgabewert eine Dock-Enumeration sein soll.

Hinweis

Die get-Zugriffsmethode für eine angefügte Eigenschaft ist für die Datenbindungsunterstützung in Entwurfstools erforderlich, z. B. Visual Studio oder Blend für Visual Studio.

Die set-Zugriffsmethode

Die set-Zugriffsmethodensignatur ist public static void Set<property name>(DependencyObject target, object value), wobei:

  • target ist das DependencyObject, in das die angefügte Eigenschaft geschrieben wird. Der target-Typ kann spezifischer sein als DependencyObject. Beispielsweise typisiert die SetDock-Methode das target-Objekt als UIElement, weil die angefügte Eigenschaft für UIElement-Instanzen festgelegt werden soll. UiElement wird indirekt von DependencyObject abgeleitet.
  • Der value-Typ kann spezifischer sein als object. Die SetDock-Methode erfordert z. B. einen Dock-Wert. Das XAML-Ladeprogramm muss den value-Typ aus der Markupzeichenfolge generieren können, die den Wert der angefügten Eigenschaft darstellt. Daher müssen Typkonvertierungen, das Werte-Serialisierungsprogramm oder Markuperweiterungen für den verwendeten Typ unterstützt werden.

Attribute von angefügten Eigenschaften

WPF definiert verschiedene .NET-Attribute, die Informationen zu angefügten Eigenschaften für Reflexionsprozesse und auch für Consumer von Reflexions- und Eigenschaftsinformationen (z. B. Designern) bereitstellen. Designer verwenden WPF-definierte .NET-Attribute, um die im Eigenschaftenfenster angezeigten Eigenschaften einzuschränken und so zu vermeiden, dass Benutzer mit einer globalen Liste aller angefügten Eigenschaften erdrückt werden. Sie sollten diese Attribute auf Ihre eigenen benutzerdefinierten angefügten Eigenschaften anwenden. Der Zweck und die Syntax von .NET-Attributen wird auf diesen Referenzseiten beschrieben:

Weitere Informationen

  • Weitere Informationen zum Erstellen einer angefügten Eigenschaft finden Sie unter Registrieren einer angefügten Eigenschaft.
  • Weitergehende Verwendungsszenarios für Abhängigkeitseigenschaften und angefügte Eigenschaften finden Sie unter Benutzerdefinierte Abhängigkeitseigenschaften.
  • Sie können eine Eigenschaft sowohl als angefügte Eigenschaft als auch als Abhängigkeitseigenschaft registrieren und herkömmliche Eigenschaftenwrapper einschließen. Auf diese Weise kann eine Eigenschaft für ein Element mithilfe von Eigenschaftenwrappern und auch für jedes andere Element mithilfe der XAML-Syntax für angefügte Eigenschaften festgelegt werden. Ein Beispiel finden Sie unter FrameworkElement.FlowDirection.

Weitere Informationen