Udostępnij za pośrednictwem


Dziedziczenie wartości właściwości

Dziedziczenie wartości właściwości jest funkcją systemu właściwości Windows Presentation Foundation (WPF) i odnosi się do właściwości zależności. Dziedziczenie wartości właściwości umożliwia elementom podrzędnym w drzewie elementów uzyskanie wartości określonej właściwości z najbliższego elementu nadrzędnego. Ponieważ element nadrzędny mógł również uzyskać wartość właściwości poprzez dziedziczenie tej wartości, system potencjalnie wykonuje proces sięgania z powrotem do korzenia strony.

System właściwości WPF domyślnie nie włącza dziedziczenia wartości właściwości, a dziedziczenie wartości jest nieaktywne, chyba że zostało to specjalnie włączone w metadanych właściwości zależności. Nawet jeśli dziedziczenie wartości właściwości jest włączone, element podrzędny będzie dziedziczyć wartość właściwości tylko wtedy, gdy nie występuje wyższa wartość priorytetu.

Wymagania wstępne

Artykuł zakłada, że posiadasz 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.

Dziedziczenie za pomocą drzewa elementów

Dziedziczenie wartości właściwości nie jest takie samo, jak dziedziczenie klas w programowaniu obiektowym, gdzie klasy pochodne dziedziczą składowe klas bazowych. Tego rodzaju dziedziczenie jest również aktywne w WPF, chociaż w XAML dziedziczone właściwości klasy bazowej są widoczne jako atrybuty elementów XAML reprezentujących klasy pochodne.

Dziedziczenie wartości właściwości to mechanizm, za pomocą którego wartość właściwości zależnej przenosi się z elementu nadrzędnego na elementy podrzędne w strukturze drzewa zawierającej tę właściwość. W znacznikach XAML drzewo elementów jest widoczne jako zagnieżdżone elementy.

Poniższy przykład przedstawia zagnieżdżone elementy w języku XAML. WPF rejestruje AllowDrop właściwość zależności w UIElement klasie z metadanymi właściwości, które umożliwiają dziedziczenie wartości właściwości i ustawia wartość domyślną na false. Właściwość AllowDrop zależności istnieje w elementach Canvas, StackPaneli Label , ponieważ wszystkie pochodzą z elementu UIElement. Ponieważ właściwość zależności AllowDrop na canvas1 jest ustawiona na true, elementy potomne stackPanel1 i label1 dziedziczą true jako swoją wartość AllowDrop.

<Canvas x:Name="canvas1" Grid.Column="0" Margin="20" Background="Orange" AllowDrop="True">
    <StackPanel Name="stackPanel1" Margin="20" Background="Green">
        <Label Name="label1" Margin="20" Height="40" Width="40" Background="Blue"/>
    </StackPanel>
</Canvas>

Można również programowo utworzyć drzewo elementów, dodając obiekty elementów do kolekcji elementów podrzędnych innego obiektu elementu. W czasie wykonywania dziedziczenie wartości właściwości funkcjonuje na wynikowym drzewie obiektów. W poniższym przykładzie stackPanel2 jest dodawany do kolekcji podrzędnejcanvas2. Podobnie, label2 jest dodawany do kolekcji podrzędnej stackPanel2. Ponieważ właściwość zależności AllowDrop na canvas2 jest ustawiona na true, elementy potomne stackPanel2 i label2 dziedziczą true jako swoją wartość AllowDrop.

Canvas canvas2 = new()
{
    AllowDrop = true
};
StackPanel stackPanel2 = new();
Label label2 = new();
canvas2.Children.Add(stackPanel2);
stackPanel2.Children.Add(label2);
Dim canvas2 As New Canvas With {
    .AllowDrop = True
}
Dim stackPanel2 As New StackPanel()
Dim label2 As New Label()
canvas2.Children.Add(stackPanel2)
stackPanel2.Children.Add(label2)

Praktyczne zastosowania dziedziczenia wartości właściwości

Określone właściwości zależności WPF mają domyślnie włączone dziedziczenie wartości, takie jak AllowDrop i FlowDirection. Zazwyczaj właściwości z dziedziczeniem wartości włączone domyślnie są implementowane na podstawowych klasach elementów interfejsu użytkownika, więc istnieją w klasach pochodnych. Na przykład ponieważ AllowDrop jest implementowana w klasie bazowej UIElement , ta właściwość zależności istnieje również na każdej kontrolce pochodzącej z UIElementklasy . WPF umożliwia dziedziczenie wartości właściwości zależności, dla których wygodne dla użytkownika jest ustawienie wartości właściwości raz w elemencie nadrzędnym, aby wartość ta była propagowana do elementów potomnych w drzewie elementów potomnych.

Model dziedziczenia wartości właściwości przypisuje wartości właściwości, zarówno dziedziczone, jak i niezaheritowane, zgodnie z pierwszeństwem wartości właściwości zależności. Dlatego wartość właściwości elementu nadrzędnego zostanie zastosowana tylko do elementu podrzędnego, jeśli właściwość elementu podrzędnego nie ma wyższej wartości pierwszeństwa, takiej jak wartość ustawiona lokalnie lub wartość uzyskana za pomocą stylów, szablonów lub powiązania danych.

Właściwość FlowDirection zależności ustawia kierunek układu tekstu i elementów podrzędnych interfejsu użytkownika w elemencie nadrzędnym. Zazwyczaj oczekuje się, że kierunek przepływu elementów tekstu i interfejsu użytkownika na stronie będzie spójny. Ponieważ dziedziczenie wartości jest włączone w właściwości metadanychFlowDirection, wartość wystarczy ustawić tylko raz na szczycie drzewa elementów dla strony. W rzadkich przypadkach, gdy dla strony jest przeznaczona mieszanka kierunków przepływu, można ustawić inny kierunek przepływu na elemencie w drzewie, przypisując lokalnie ustawioną wartość. Nowy kierunek przepływu będzie następnie propagowany do elementów podrzędnych poniżej tego poziomu.

Tworzenie dziedzicznej właściwości niestandardowej

Właściwość zależności niestandardowej można dziedziczyć, przez włączenie właściwości Inherits w wystąpieniu FrameworkPropertyMetadata, a następnie rejestrując niestandardową właściwość zależności w tych metadanych. Domyślnie Inherits wartość jest ustawiona na wartość w elemfalse.FrameworkPropertyMetadata Dziedziczenie wartości właściwości wpływa na wydajność, więc ustaw Inherits wartość na true wartość tylko wtedy, gdy ta funkcja jest potrzebna.

Podczas rejestrowania właściwości zależności z włączoną funkcją w metadanych, użyj metody Inherits zgodnie z opisem w sekcji RegisterAttached. Ponadto przypisz wartość domyślną do właściwości, aby istniała wartość dziedziczona. Możesz również utworzyć otokę właściwości i getset metody dostępu dla typu właściciela, tak jak w przypadku właściwości zależności nieprzyłączonej. W ten sposób można ustawić wartość właściwości przy użyciu otoki właściwości dla właściciela lub typu pochodnego. Poniższy przykład tworzy właściwość zależności o nazwie IsTransparent, z włączonym Inherits i domyślną wartością false. Przykład zawiera również opakowanie właściwości z metodami dostępu get i set.

public class Canvas_IsTransparentInheritEnabled : Canvas
{
    // Register an attached dependency property with the specified
    // property name, property type, owner type, and property metadata
    // (default value is 'false' and property value inheritance is enabled).
    public static readonly DependencyProperty IsTransparentProperty =
        DependencyProperty.RegisterAttached(
            name: "IsTransparent",
            propertyType: typeof(bool),
            ownerType: typeof(Canvas_IsTransparentInheritEnabled),
            defaultMetadata: new FrameworkPropertyMetadata(
                defaultValue: false,
                flags: FrameworkPropertyMetadataOptions.Inherits));

    // Declare a get accessor method.
    public static bool GetIsTransparent(Canvas element)
    {
        return (bool)element.GetValue(IsTransparentProperty);
    }

    // Declare a set accessor method.
    public static void SetIsTransparent(Canvas element, bool value)
    {
        element.SetValue(IsTransparentProperty, value);
    }

    // For convenience, declare a property wrapper with get/set accessors.
    public bool IsTransparent
    {
        get => (bool)GetValue(IsTransparentProperty);
        set => SetValue(IsTransparentProperty, value);
    }
}
Public Class Canvas_IsTransparentInheritEnabled
    Inherits Canvas

    ' Register an attached dependency property with the specified
    ' property name, property type, owner type, and property metadata
    ' (default value is 'false' and property value inheritance is enabled).
    Public Shared ReadOnly IsTransparentProperty As DependencyProperty =
        DependencyProperty.RegisterAttached(
            name:="IsTransparent",
            propertyType:=GetType(Boolean),
            ownerType:=GetType(Canvas_IsTransparentInheritEnabled),
            defaultMetadata:=New FrameworkPropertyMetadata(
                defaultValue:=False,
                flags:=FrameworkPropertyMetadataOptions.[Inherits]))

    ' Declare a get accessor method.
    Public Shared Function GetIsTransparent(element As Canvas) As Boolean
        Return element.GetValue(IsTransparentProperty)
    End Function

    ' Declare a set accessor method.
    Public Shared Sub SetIsTransparent(element As Canvas, value As Boolean)
        element.SetValue(IsTransparentProperty, value)
    End Sub

    ' For convenience, declare a property wrapper with get/set accessors.
    Public Property IsTransparent As Boolean
        Get
            Return GetValue(IsTransparentProperty)
        End Get
        Set(value As Boolean)
            SetValue(IsTransparentProperty, value)
        End Set
    End Property
End Class

Dołączone właściwości są koncepcyjnie podobne do właściwości globalnych. Możesz sprawdzić ich wartość na dowolnym DependencyObject obiekcie i uzyskać prawidłowy wynik. Typowy scenariusz dla dołączonych właściwości polega na ustawieniu wartości właściwości na elementach podrzędnych, a ten scenariusz jest bardziej skuteczny, jeśli właściwość, o którą mowa, jest niejawnie obecna jako dołączona właściwość dla każdego DependencyObject elementu w drzewie.

Dziedziczenie wartości właściwości między granicami drzewa

Dziedziczenie właściwości działa przez przechodzenie przez drzewo elementów. To drzewo jest często równoległe do drzewa logicznego. Jednak za każdym razem, gdy uwzględnisz obiekt na poziomie rdzenia WPF, taki jak Brush, w znaczniku definiującym drzewo elementów, utworzono nieciągłe drzewo logiczne. Prawdziwe drzewo logiczne nie rozciąga się koncepcyjnie przez Brushelement , ponieważ drzewo logiczne jest koncepcją na poziomie platformy WPF. Metody pomocnicze LogicalTreeHelper umożliwiają analizowanie i wyświetlanie zakresu drzewa logicznego. Dziedziczenie wartości właściwości jest w stanie przekazać dziedziczone wartości za pośrednictwem nieciągłego drzewa logicznego, ale tylko wtedy, gdy właściwość dziedziczona została zarejestrowana jako dołączona właściwość i nie ma celowej granicy blokującej dziedziczenie, takiej jak Frame.

Uwaga / Notatka

Mimo że dziedziczenie wartości właściwości może wydawać się działać dla nieprzyłączone właściwości zależności, zachowanie dziedziczenia dla właściwości nieprzyłączonej przez niektóre granice elementów w drzewie środowiska uruchomieniowego jest niezdefiniowane. Za każdym razem, gdy określisz Inherits w metadanych właściwości, zarejestruj twoje właściwości używając RegisterAttached.

Zobacz także