XAML-Lade- und Abhängigkeitseigenschaften (WPF .NET)
Die Implementierung des Extensible Application Markup Language (XAML)-Prozessors der Windows Presentation Foundation (WPF) ist von Natur aus auf Abhängigkeitseigenschaften ausgelegt. Daher verwendet der XAML-Prozessor WPF-Eigenschaftensystemmethoden zum Laden von XAML- und Prozessabhängigkeitseigenschaftenattributen und umgeht vollständig Abhängigkeitseigenschaftenwrapper mithilfe von WPF-Eigenschaftensystemmethoden wie GetValue und SetValue. Wenn Sie also benutzerdefinierte Logik zum Eigenschaften-Wrapper Ihrer benutzerdefinierten Abhängigkeitseigenschaft hinzufügen, wird diese nicht vom XAML-Prozessor aufgerufen, wenn ein Eigenschaftswert in XAML festgelegt wird.
Voraussetzungen
In diesem Artikel wird vorausgesetzt, dass Sie ein grundlegendes Wissen über Abhängigkeitseigenschaften haben und Ü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.
Leistung des WPF-XAML-Ladeprogramms
Für den WPF-XAML-Prozessor ist es rechnerisch weniger aufwendig, SetValue direkt aufzurufen, um den Wert einer Abhängigkeitseigenschaft festzulegen, anstatt den Eigenschaften-Wrapper einer Abhängigkeitseigenschaft zu verwenden.
Wenn der XAML-Prozessor den Eigenschaftenwrapper verwenden würde, müsste das gesamte Objektmodell des Sicherungscodes nur basierend auf den Typ- und Memberbeziehungen abgeleitet werden, die im Markup angegeben sind. Obwohl der Typ anhand von Markup durch eine Kombination aus xmlns
- und Assemblyattributen identifiziert werden kann, wären zum Identifizieren der Member, um zu bestimmen, welche Member als Attribut festgelegt werden können, und zum Auflösen der unterstützten Eigenschaftswerttypen umfassende Reflektionen mit PropertyInfoerforderlich.
Das WPF-Eigenschaftensystem verwaltet eine Speichertabelle mit Abhängigkeitseigenschaften, die für einen bestimmten DependencyObject abgeleiteten Typ implementiert wurden. Der XAML-Prozessor verwendet diese Tabelle, um den Abhängigkeitseigenschaftsbezeichner für eine Abhängigkeitseigenschaft abzuleiten. Der Bezeichner einer Abhängigkeitseigenschaft, die den Namen ABC
trägt, ist beispielsweise gemäß Konvention ABCProperty
. Der XAML-Prozessor kann den Wert jeder Abhängigkeitseigenschaft effizient festlegen, indem die SetValue
-Methode für den zugehörigen Typ mithilfe des Abhängigkeitseigenschaftsbezeichners aufgerufen wird.
Weitere Informationen zu den Wrappern für Abhängigkeitseigenschaften finden Sie unter Benutzerdefinierte Abhängigkeitseigenschaften.
Auswirkungen auf benutzerdefinierte Abhängigkeitseigenschaften
Der WPF-XAML-Prozessor umgeht Eigenschaftsumschläge und ruft direkt SetValue auf, um den Wert einer Abhängigkeitseigenschaft festzulegen. Vermeiden Sie daher, zusätzliche Logik in den set
Accessor Ihrer benutzerdefinierten Abhängigkeitseigenschaft einzufügen, da diese Logik nicht ausgeführt wird, wenn ein Eigenschaftswert in XAML festgelegt wird. Der set
-Accessor sollte nur einen SetValue
-Aufruf enthalten.
Ebenso umgeht der WPF-XAML-Prozessor beim Abrufen von Eigenschaftswerten den Eigenschaftenwrapper und ruft direkt GetValueauf. Vermeiden Sie daher auch das Einfügen zusätzlicher Logik in den get
Accessor Ihrer benutzerdefinierten Abhängigkeitseigenschaft, da diese Logik nicht ausgeführt wird, wenn ein Eigenschaftswert in XAML gelesen wird. Der get
-Accessor soll nur einen GetValue
-Aufruf enthalten.
Abhängigkeitseigenschaft mit einem Wrapperbeispiel
Das folgende Beispiel zeigt eine empfohlene Definition der Abhängigkeitseigenschaft mit Eigenschaftenwrappern. Der Bezeichner der Abhängigkeitseigenschaft wird als ein public static readonly
-Feld gespeichert, und die Accessor-Methoden get
und set
enthalten keinen Code außer den erforderlichen WPF-Eigenschaftensystemmethoden, die den Wert der Abhängigkeitseigenschaft unterstützen. Wenn Sie Code haben, der ausgeführt werden muss, wenn sich der Wert Ihrer Abhängigkeitseigenschaft ändert, sollten Sie diesen Code in die PropertyChangedCallback für Ihre Abhängigkeitseigenschaft einfügen. Weitere Informationen finden Sie unter Eigenschaftsänderungs-Callbacks.
// Register a dependency property with the specified property name,
// property type, owner type, and property metadata. Store the dependency
// property identifier as a public static readonly member of the class.
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,
propertyChangedCallback: new PropertyChangedCallback(OnUriChanged))
);
// Property wrapper with get & set accessors.
public Uri AquariumGraphic
{
get => (Uri)GetValue(AquariumGraphicProperty);
set => SetValue(AquariumGraphicProperty, value);
}
// Property-changed callback.
private static void OnUriChanged(DependencyObject dependencyObject,
DependencyPropertyChangedEventArgs e)
{
// Some custom logic that runs on effective property value change.
Uri newValue = (Uri)dependencyObject.GetValue(AquariumGraphicProperty);
Debug.WriteLine($"OnUriChanged: {newValue}");
}
' Register a dependency property with the specified property name,
' property type, owner type, and property metadata. Store the dependency
' property identifier as a public static readonly member of the class.
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,
propertyChangedCallback:=New PropertyChangedCallback(AddressOf OnUriChanged)))
' Property 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
' Property-changed callback.
Private Shared Sub OnUriChanged(dependencyObject As DependencyObject,
e As DependencyPropertyChangedEventArgs)
' Some custom logic that runs on effective property value change.
Dim newValue As Uri = CType(dependencyObject.GetValue(AquariumGraphicProperty), Uri)
Debug.WriteLine($"OnUriChanged: {newValue}")
End Sub
Siehe auch
.NET Desktop feedback