Übersicht über angefügte Eigenschaften
Eine angefügte Eigenschaft ist ein von XAML definiertes Konzept. Eine angefügte Eigenschaft ist für die Verwendung als Typ einer globalen Eigenschaft vorgesehen, der in jedem Abhängigkeitsobjekt festgelegt werden kann. In Windows Presentation Foundation (WPF) werden angefügte Eigenschaften in der Regel als eine spezielle Form der Abhängigkeitseigenschaft definiert, die nicht die herkömmliche Eigenschaft „Wrapper“ aufweist.
Voraussetzungen
In diesem Artikel wird vorausgesetzt, dass Sie sich mit Abhängigkeitseigenschaften aus Sicht von vorhandenen Abhängigkeitseigenschaften von Consumern in WPF-Klassen (Windows Presentation Foundation) auskennen und Übersicht über Abhängigkeitseigenschaften gelesen haben. Um die Beispiele in diesem Artikel nachvollziehen zu können, sollten Sie zudem XAML verstehen und wissen, wie WPF-Anwendungen geschrieben werden.
Warum angefügte Eigenschaften verwendet werden sollen
Ein Zweck einer angefügten Eigenschaft ist die Berechtigung für verschiedene untergeordnete Elemente, eindeutige Werte für eine Eigenschaft anzugeben, die in einem übergeordneten Element definiert ist. Eine spezifische Anwendung dieses Szenarios besteht darin, dass untergeordnete Elemente das übergeordnete Element darüber informieren, wie sie in der Benutzeroberfläche dargestellt werden sollen. Ein Beispiel hierfür ist die DockPanel.Dock-Eigenschaft. Die DockPanel.Dock-Eigenschaft wird als angefügte Eigenschaft erstellt, da sie dazu bestimmt ist, für Elemente festgelegt zu werden, die in einem DockPanel enthalten sind, und nicht für DockPanel selbst. Die DockPanel-Klasse definiert das statische DependencyProperty-Feld mit dem Namen DockProperty und stellt dann die 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 AttachedPropertyProvider.PropertyName fest.
Im Folgenden finden Sie ein Beispiel für das Festlegen von DockPanel.Dock in XAML:
<DockPanel>
<TextBox DockPanel.Dock="Top">Enter text</TextBox>
</DockPanel>
Die Verwendung ähnelt einer statischen Eigenschaft. Sie verweisen immer auf den Typ DockPanel, der die angefügte Eigenschaft besitzt und registriert, anstatt auf eine beliebige Instanz anhand des Namens zu verweisen.
Da eine angefügte Eigenschaft in XAML ein Attribut ist, das Sie im Markup festlegen, besitzt außerdem nur der Mengenvorgang Relevanz. Sie können eine Eigenschaft in XAML nicht direkt abrufen, obwohl einige indirekte Mechanismen zum Vergleichen von Werten vorhanden sind, wie z.B. Trigger in Formaten (weitere Informationen finden Sie unter Erstellen von Formaten und Vorlagen).
Implementierung von angefügten Eigenschaften in WPF
In WPF (Windows Presentation Foundation) sind die meisten der benutzeroberflächenbezogenen angefügten Eigenschaften von WPF-Typen als Abhängigkeitseigenschaften implementiert. Angefügte Eigenschaften sind ein XAML-Konzept, wohingegen Abhängigkeitseigenschaften ein WPF-Konzept sind. Da angefügte Eigenschaften von WPF Abhängigkeitseigenschaften sind, unterstützen sie die Konzepte von Abhängigkeitseigenschaften, darunter z. B. Eigenschaftenmetadaten und Standardwerte aus diesen Eigenschaftenmetadaten.
Wie angefügte Eigenschaften durch den besitzenden Typ verwendet werden
Obwohl angefügte Eigenschaften für jedes beliebige Objekt festgelegt werden können, bedeutet dies nicht automatisch, dass die Eigenschaft ein reales Ergebnis erzeugt, oder der Wert jemals von einem anderen Objekt verwendet wird. Im Allgemeinen werden angefügte Eigenschaften vorgesehen, damit Objekte, die aus einer Vielzahl von möglichen Klassenhierarchien oder logischen Beziehungen stammen, dem Typ, der die angefügte Eigenschaft definiert, allgemeine Informationen melden können. Der Typ, der die angefügte Eigenschaft definiert, folgt in der Regel einem dieser Modelle:
Der Typ, der die angefügte Eigenschaft definiert, ist so konzipiert, dass er das übergeordnete Element der Elemente sein kann, das Werte für die angefügte Eigenschaft festlegen wird. Der Typ durchläuft dann seine untergeordneten Objekte durch die interne Logik auf der Grundlage der Objektstruktur, ruft die Werte ab und fungiert auf irgendeine Weise für diese Werte.
Der Typ, der die angefügte Eigenschaft definiert, wird als untergeordnetes Element für verschiedene mögliche übergeordnete Elemente und Inhaltsmodelle verwendet werden.
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 häufigste Szenario, in dem WPF eine angefügte Eigenschaft definiert: Wenn ein übergeordnetes Element eine Auflistung untergeordneter Elemente unterstützt und zusätzlich ein Verhalten implementiert, in dem die Einzelheiten des Verhaltens für jedes untergeordnete Element einzeln gemeldet werden.
DockPanel definiert die angefügte DockPanel.Dock-Eigenschaft, und DockPanel verfügt über Code auf Klassenebene als Teil der Renderinglogik (insbesondere MeasureOverride und ArrangeOverride). Eine DockPanel-Instanz überprüft immer, ob eines ihrer unmittelbaren untergeordneten Elemente einen Wert für DockPanel.Dock festgelegt hat. Wenn dies der Fall ist, werden diese Werte zur Eingabe für die Renderinglogik, die auf das jeweilige untergeordnete Element angewendet wird. Geschachtelte DockPanel-Instanzen behandeln jeweils ihre eigenen unmittelbaren untergeordneten Elementsammlungen, aber dieses Verhalten ist implementierungsspezifisch und hängt davon ab, wie DockPanelDockPanel.Dock-Werte verarbeitet. Es ist theoretisch möglich, angefügte Eigenschaften zu besitzen, die Elemente über das unmittelbar übergeordnete Element hinaus beeinflussen. Wenn die angefügte DockPanel.Dock-Eigenschaft auf ein Element festgelegt wird, das kein übergeordnetes DockPanel-Element besitzt, mit dem interagiert werden kann, wird kein Fehler und auch keine Ausnahme ausgelöst. Dies bedeutet einfach, dass ein globaler Eigenschaftswert festgelegt wurde, aber dass er über kein übergeordnetes Element DockPanel verfügt, das die Informationen nutzen könnte.
Angefügte Eigenschaften in Code
Angefügte Eigenschaften in WPF besitzen nicht die normalen CLR-„Wrapper“-Methoden für den einfachen Get/Set-Zugriff. Dies liegt daran, dass die angefügte Eigenschaft nicht unbedingt Teil des CLR-Namespaces für Instanzen ist, in denen die Eigenschaft festgelegt ist. Allerdings muss ein XAML-Prozessor in der Lage sein, diese Werte festzulegen, wenn XAML analysiert wird. Für die Unterstützung zur Verwendung einer effektiven angefügten Eigenschaft muss der Besitzertyp der angefügten Eigenschaft dedizierte Zugriffsmethoden im Formular GetPropertyName und SetPropertyName implementieren. Diese dedizierten Accessormethoden eignen sich auch zum Abrufen oder Festlegen der angefügten Eigenschaft im Code. Im Hinblick auf Code ist eine angefügte Eigenschaft einem dahinter liegenden Feld ähnlich, das Methodenaccessoren anstelle von Eigenschaftenaccessoren besitzt, und das dahinter liegende Feld kann in jedem Objekt vorhanden sein, anstatt explizit definiert werden zu müssen.
Das folgende Beispiel zeigt, wie Sie eine angefügte Eigenschaft im Code festlegen können. In diesem Codebeispiel ist myCheckBox
eine Instanz der CheckBox-Klasse.
DockPanel myDockPanel = new DockPanel();
CheckBox myCheckBox = new CheckBox();
myCheckBox.Content = "Hello";
myDockPanel.Children.Add(myCheckBox);
DockPanel.SetDock(myCheckBox, Dock.Top);
Dim myDockPanel As New DockPanel()
Dim myCheckBox As New CheckBox()
myCheckBox.Content = "Hello"
myDockPanel.Children.Add(myCheckBox)
DockPanel.SetDock(myCheckBox, Dock.Top)
Ähnlich wie im XAML-Fall: Wenn myCheckBox
nicht bereits als ein untergeordnetes Element von myDockPanel
durch die vierte Zeile des Codes hinzugefügt worden wäre, würde die fünfte Zeile des Codes keine Ausnahme auslösen, aber der Wert der Eigenschaft würde nicht mit einem übergeordneten Element DockPanel interagieren und somit würde nichts geschehen. Nur ein für ein untergeordnetes Element festgelegter Wert DockPanel.Dock in Verbindung mit dem Vorhandensein eines übergeordneten Elements DockPanel führt zu einem effektiven Verhalten in der gerenderten Anwendung. (In diesem Fall könnten Sie die angefügte Eigenschaft festlegen und dann an die Struktur anfügen. Oder fügen zuerst an die Struktur an und legen dann die angefügte Eigenschaft fest. Beide Vorgehensweisen führen zum gleichen Ergebnis.)
Metadaten von angefügten Eigenschaften
Bei der Registrierung der Eigenschaft wird FrameworkPropertyMetadata festgelegt, um die Merkmale der Eigenschaft anzugeben, z. B. ob die Eigenschaft das Rendering, die Messung usw. beeinflusst. Metadaten für eine angefügte Eigenschaft unterscheiden sich im Allgemeinen nicht von denen für eine Abhängigkeitseigenschaft. Wenn Sie einen Standardwert in einer Überschreibung für die Metadaten von angefügten Eigenschaften angeben, wird dieser Wert der Standardwert der impliziten angefügten Eigenschaft in Instanzen der überschreibenden Klasse. Der Standardwert wird insbesondere gemeldet, wenn ein Prozess den Wert einer angefügten Eigenschaft über die Get
-Methodenaccessoren für diese Eigenschaft abfragt, die eine Instanz der Klasse angibt, in dem Sie die Metadaten festgelegt haben, und wenn der Wert für diese angefügte Eigenschaft andernfalls nicht festgelegt war.
Wenn Sie die Vererbung von Eigenschaftswerten für eine Eigenschaft aktivieren möchten, sollten Sie die angefügten Eigenschaften anstelle von nicht angefügten Abhängigkeitseigenschaften verwenden. Weitere Informationen finden Sie unter Vererbung von Eigenschaftswerten.
Benutzerdefinierte angefügte Eigenschaften
Wann eine angefügte Eigenschaft erstellt werden soll
Sie können eine angefügte Eigenschaft erstellen, wenn ein Mechanismus für Eigenschafteneinstellungen für andere Klassen als die definierende Klasse zur Verfügung stehen muss. Das gängigste Szenario hierfür ist Layout. Beispiele für vorhandene Layouteigenschaften sind DockPanel.Dock, Panel.ZIndexund Canvas.Top. Das hier aktivierte Szenario: Elemente, die als untergeordnete Elemente für das Layout steuernde Elemente vorhanden sind, können Layoutanforderungen einzeln an die übergeordneten Layoutelemente stellen, für jede Einstellung einen Eigenschaftswert, den das übergeordnete Element als angefügte Eigenschaft definiert.
Ein weiteres Szenario für die Verwendung einer angefügten Eigenschaft: Wenn Ihre Klasse einen Dienst darstellt und Sie möchten, dass Klassen den Dienst auf transparentere Weise integrieren können.
Ein weiteres Szenario ist Unterstützung durch Visual Studio WPF Designer, z. B. die Bearbeitung von Eigenschaftenfenstern. Weitere Informationen finden Sie unter Übersicht über das Erstellen von Steuerelementen.
Wie bereits erwähnt, sollten Sie als eine angefügte Eigenschaft registrieren, wenn Sie die Vererbung von Eigenschaftswerten verwenden möchten.
So erstellen Sie eine angefügte Eigenschaft
Wenn Ihre Klasse die angefügte Eigenschaft nur für die Verwendung für andere Typen definiert, muss die Klasse nicht von DependencyObject abgeleitet sein. Aber Sie müssen von DependencyObject ableiten, wenn Sie dem allgemeinen WPF-Modell folgen, bei dem die angefügte Eigenschaft auch eine Abhängigkeitseigenschaft ist.
Definieren Sie die angefügte Eigenschaft als Abhängigkeitseigenschaft, indem Sie ein Feld public static readonly
des Typs DependencyProperty deklarieren. Sie definieren dieses Feld, indem Sie den Rückgabewert der RegisterAttached-Methode verwenden. Der Feldname muss mit dem Namen der angefügten Eigenschaft übereinstimmen, angefügt mit der Zeichenfolge Property
, um dem geltenden WPF-Muster für die Benennung der identifizierenden Felder im Vergleich zu den Eigenschaften, die sie darstellen, zu folgen. Der angefügte Eigenschaftenanbieter muss auch die statische Methoden GetPropertyName und SetPropertyName als Zugriffsmethoden für die angefügte Eigenschaft bereitstellen. Andernfalls führt dies dazu, dass das Eigenschaftensystem Ihre angefügte Eigenschaft nicht verwenden kann.
Hinweis
Wenn Sie den Get-Accessor der angefügten Eigenschaft auslassen, wird die Datenbindung für die Eigenschaft in Entwurfstools (z. B. Visual Studio und Blend für Visual Studio) nicht funktionieren.
Der Get-Accessor
Die Zugriffsmethode GetPropertyName muss die folgende Signatur aufweisen:
public static object GetPropertyName(object target)
Das
target
-Objekt kann als spezifischerer Typ in Ihrer Implementierung angegeben werden. Beispielsweise typisiert die DockPanel.GetDock-Methode den Parameter als UIElement, weil die angefügte Eigenschaft nur für UIElement-Instanzen festgelegt werden soll.Der Rückgabewert kann als spezifischerer Typ in Ihrer Implementierung angegeben werden. Die GetDock-Methode typisiert ihn beispielsweise als Dock, da der Wert nur auf diese Enumeration festgelegt werden kann.
Der Set-Accessor
Für die Zugriffsmethode SetPropertyName muss die folgende Signatur verwendet werden:
public static void SetPropertyName(object target, object value)
Das
target
-Objekt kann als spezifischerer Typ in Ihrer Implementierung angegeben werden. Beispielsweise typisiert es die SetDock-Methode als UIElement, weil die angefügte Eigenschaft nur für UIElement-Instanzen festgelegt werden soll.Das
value
-Objekt kann als spezifischerer Typ in Ihrer Implementierung angegeben werden. Die SetDock-Methode typisiert es beispielsweise als Dock, da der Wert nur auf diese Enumeration festgelegt werden kann. Denken Sie daran, dass der Wert für diese Methode die Eingabe des XAML-Loaders ist, wenn sie Ihre angefügte Eigenschaft in einer Verwendung der angefügten Eigenschaft im Markup erkennt. Diese Eingabe ist der Wert, der als XAML-Attributwert im Markup angegeben wird. Aus diesem Grund muss die Typkonvertierung, das Wertserialisierungsprogramm oder die Unterstützung von Markuperweiterungen für den verwendeten Typ vorhanden sein, damit der entsprechende Typ aus dem Attributwert (der letztendlich nur eine Zeichenfolge ist) erstellt werden kann.
Das folgende Beispiel zeigt die Registrierung der Abhängigkeitseigenschaft (unter Verwendung der RegisterAttached-Methode) sowie die Zugriffsmethoden GetPropertyName und SetPropertyName. Im Beispiel ist der Name der angefügten Eigenschaft IsBubbleSource
. Deshalb müssen die Accessoren GetIsBubbleSource
und SetIsBubbleSource
genannt werden.
public static readonly DependencyProperty IsBubbleSourceProperty = DependencyProperty.RegisterAttached(
"IsBubbleSource",
typeof(Boolean),
typeof(AquariumObject),
new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsRender)
);
public static void SetIsBubbleSource(UIElement element, Boolean value)
{
element.SetValue(IsBubbleSourceProperty, value);
}
public static Boolean GetIsBubbleSource(UIElement element)
{
return (Boolean)element.GetValue(IsBubbleSourceProperty);
}
Public Shared ReadOnly IsBubbleSourceProperty As DependencyProperty = DependencyProperty.RegisterAttached("IsBubbleSource", GetType(Boolean), GetType(AquariumObject), New FrameworkPropertyMetadata(False, FrameworkPropertyMetadataOptions.AffectsRender))
Public Shared Sub SetIsBubbleSource(ByVal element As UIElement, ByVal value As Boolean)
element.SetValue(IsBubbleSourceProperty, value)
End Sub
Public Shared Function GetIsBubbleSource(ByVal element As UIElement) As Boolean
Return CType(element.GetValue(IsBubbleSourceProperty), Boolean)
End Function
Attribute von angefügten Eigenschaften
WPF definiert verschiedene .NET-Attribute, die Informationen zu angefügten Eigenschaften für Reflexionsprozesse und für typische Benutzer von Reflexions- und Eigenschaftsinformationen (z. B. Designern) bereitstellen sollen. Da angefügte Eigenschaften einen uneingeschränkten Bereich haben, benötigen Entwickler eine Möglichkeit, Benutzer nicht durch eine globale Liste aller angefügten Eigenschaften zu überwältigen, die in einer bestimmten Implementierung von Technologie definiert sind, die XAML verwendet. Die .NET-Attribute, die WPF für angefügte Eigenschaften definiert, können verwendet werden, um die Situationen festzulegen, in denen eine angefügte Eigenschaft in einem Eigenschaftenfenster angezeigt werden soll. Sie sollten diese Attribute auch auf Ihre eigenen benutzerdefinierten angefügten Eigenschaften anwenden. Der Zweck und die Syntax der .NET-Attribute wird auf den entsprechenden Referenzseiten beschrieben:
Weitere Informationen zu angefügten Eigenschaften
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 auch eine Eigenschaft als angefügte Eigenschaft und als Abhängigkeitseigenschaft registrieren, dann jedoch trotzdem „Wrapper“-Implementierungen offenlegen. In diesem Fall kann die Eigenschaft entweder auf das Element festgelegt werden, oder auf ein beliebiges Element über die angefügte XAML-Eigenschaftssyntax. Ein Beispiel für eine Eigenschaft mit einem geeigneten Szenario sowohl für Standard- als auch für angefügte Verwendung ist FrameworkElement.FlowDirection.
Weitere Informationen
.NET Desktop feedback