Udostępnij za pośrednictwem


Właściwości ładowania i zależności XAML (WPF .NET)

Implementacja programu Windows Presentation Foundation (WPF) procesora Extensible Application Markup Language (XAML) jest z natury świadoma właściwości zależności. W związku z tym procesor XAML używa metod systemu właściwości WPF do ładowania atrybutów właściwości XAML i przetwarzania właściwości i całkowicie pomija otoki właściwości zależności przy użyciu metod systemowych właściwości WPF, takich jak GetValue i SetValue. Dlatego jeśli dodasz logikę niestandardową do otoki właściwości niestandardowej właściwości zależności, nie będzie ona wywoływana przez procesor XAML, gdy wartość właściwości jest ustawiona w języku XAML.

Wymagania wstępne

W tym artykule przyjęto założenie, że masz podstawową wiedzę na temat właściwości zależności i zapoznasz się z omówieniem 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ść modułu ładującego XAML WPF

Procesor XAML WPF jest obliczanie mniej kosztowny, aby bezpośrednio wywołać SetValue metodę ustawiania wartości właściwości zależności, zamiast używać otoki właściwości zależności.

Jeśli procesor XAML używał otoki właściwości, wymagałoby wnioskowania całego modelu obiektu kodu zapasowego tylko na podstawie relacji typu i składowych wskazanych w adiustacji. Mimo że typ można zidentyfikować na podstawie znaczników przy użyciu kombinacji atrybutów xmlns zestawu i identyfikowania elementów członkowskich, określania, które elementy członkowskie można ustawić jako atrybut i rozpoznawania obsługiwanych typów wartości właściwości, wymagałoby obszernego odbicia przy użyciu polecenia PropertyInfo.

System właściwości WPF utrzymuje tabelę magazynową właściwości zależności zaimplementowanych na danym DependencyObject typie pochodnym. 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 to ABCProperty. Procesor XAML może efektywnie ustawić wartość dowolnej właściwości zależności, wywołując SetValue metodę na jej typ zawierający przy użyciu identyfikatora właściwości zależności.

Aby uzyskać więcej informacji na temat otoek 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 otoki właściwości i bezpośrednio wywołuje SetValue w celu ustawienia wartości właściwości zależności. Dlatego należy unikać umieszczania dodatkowej logiki w set metodzie dostępu niestandardowej właściwości zależności, ponieważ ta logika nie będzie uruchamiana, gdy wartość właściwości jest ustawiona w języku XAML. Akcesorium set powinno zawierać tylko wywołanie SetValue .

Podobnie aspekty procesora XAML WPF, które pobierają wartości właściwości pomijają otokę właściwości i bezpośrednio wywołają metodę GetValue. Dlatego należy również unikać umieszczania dodatkowej logiki w get metodzie 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. Akcesorium get powinno zawierać tylko wywołanie GetValue .

Przykład właściwości zależności z otoki

W poniższym przykładzie przedstawiono zalecaną definicję właściwości zależności z otokami właściwości. Identyfikator właściwości zależności jest przechowywany jako public static readonly pole, a get metody dostępu i set nie zawierają kodu poza wymaganymi metodami systemu właściwości WPF, które są z powrotem wartości właściwości zależności. Jeśli masz kod, który musi być uruchamiany, gdy wartość właściwości zależności ulegnie zmianie, rozważ umieszczenie tego kodu we PropertyChangedCallback właściwości zależności. Aby uzyskać więcej informacji, zobacz Wywołania zwrotne zmienione 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ż