Właściwości ładowania i zależności XAML (WPF .NET)
Implementacja procesora Extensible Application Markup Language (XAML) w Windows Presentation Foundation (WPF) jest przystosowana do obsługi właściwości zależności. W związku z tym procesor XAML używa metod systemowych właściwości WPF do ładowania XAML i przetwarzania atrybutów właściwości zależności, całkowicie pomijając otoki właściwości zależności, korzystając z metod systemowych właściwości WPF, takich jak GetValue i SetValue. Dlatego jeśli dodasz niestandardową logikę do otoczki właściwości dla niestandardowej właściwości zależności, logika ta nie zostanie wywołana przez procesor XAML, gdy wartość właściwości jest ustawiana w XAML.
Warunki wstępne
W artykule przyjęto założenie, że masz podstawową wiedzę na temat właściwości zależności i że przeczytałeś omówienie właściwości zależności . Aby postępować zgodnie z przykładami w tym artykule, warto zapoznać się z językiem Extensible Application Markup Language (XAML) i wiedzieć, jak pisać aplikacje WPF.
Wydajność ładowania WPF XAML
Procesor XAML WPF jest mniej obciążające obliczeniowo, aby bezpośrednio wywołać SetValue w celu ustawienia wartości właściwości zależności, zamiast używać opakowania właściwości zależności.
Jeśli procesor XAML używałby otoczki właściwości, wymagałoby to wywodzenia całego modelu obiektu kodu źródłowego tylko na podstawie wskazanych w znacznikach relacji typu i członków. Chociaż typ można zidentyfikować na podstawie znaczników, używając połączenia atrybutów xmlns
i atrybutów zestawu, identyfikacja elementów członkowskich, określenie, które z nich mogą być ustawione jako atrybuty, oraz rozpoznanie obsługiwanych typów wartości właściwości wymagałoby intensywnego użycia refleksji za pomocą PropertyInfo.
System właściwości WPF utrzymuje tabelę przechowywania właściwości zależnych zaimplementowanych na określonym typie pochodnym DependencyObject. Procesor XAML używa tej tabeli do wnioskowania identyfikatora właściwości zależności dla właściwości zależności. Na przykład zgodnie z konwencją identyfikator właściwości zależności dla właściwości zależności o nazwie ABC
jest ABCProperty
. Procesor XAML może efektywnie ustawić wartość dowolnej właściwości zależności, wywołując metodę SetValue
dla jej typu zawierającego przy użyciu identyfikatora właściwości zależności.
Aby uzyskać więcej informacji na temat opakowań właściwości zależności, zobacz Niestandardowe właściwości zależności.
Implikacje dotyczące niestandardowych właściwości zależności
Procesor WPF XAML pomija opakowania właściwości i bezpośrednio wywołuje SetValue, aby ustawić wartość właściwości zależnej. Dlatego należy unikać umieszczania dodatkowej logiki w set
metod dostępu niestandardowej właściwości zależności, ponieważ ta logika nie zostanie uruchomiona, gdy wartość właściwości jest ustawiona w języku XAML. Akcesor set
powinien zawierać tylko wywołanie SetValue
.
Podobnie aspekty procesora WPF XAML, które pobierają wartości właściwości, pomijają otokę właściwości i bezpośrednio wywołują metodę GetValue. Dlatego należy unikać umieszczania dodatkowej logiki w get
metod dostępu niestandardowej właściwości zależności, ponieważ ta logika nie będzie uruchamiana, gdy wartość właściwości jest odczytywana w języku XAML. Akcesor get
powinien zawierać tylko wywołanie GetValue
.
Przykład właściwości zależności z opakowaniem
W poniższym przykładzie przedstawiono zalecaną definicję właściwości zależności z osłonkami właściwości. Identyfikator właściwości zależności jest przechowywany jako pole public static readonly
, a get
i set
metody dostępu nie zawierają żadnego kodu poza niezbędnymi metodami systemu właściwości WPF, które obsługują wartość właściwości zależności. Jeśli masz kod, który musi zostać uruchomiony, gdy wartość właściwości zależności ulegnie zmianie, rozważ umieszczenie tego kodu w PropertyChangedCallback dla właściwości zależności. Aby uzyskać więcej informacji, zobacz wywołania zwrotne dla zmian właściwości.
// 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
Zobacz też
- Właściwości zależności — omówienie
- XAML w WPF
- Niestandardowe właściwości zależności
- Metadane właściwości zależności
- właściwości zależności typu kolekcji
- zabezpieczenia właściwości zależności
- Bezpieczne wzorce konstruktorów dla DependencyObjects
.NET Desktop feedback