Dziedziczenie wartości właściwości (WPF .NET)

Dziedziczenie wartości właściwości jest funkcją systemu właściwości Windows Presentation Foundation (WPF) i ma zastosowanie 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ć jego wartość właściwości za pośrednictwem dziedziczenia wartości właściwości, system potencjalnie powtarza się z powrotem do katalogu głównego 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 w przypadku włączenia dziedziczenia wartości właściwości element podrzędny będzie dziedziczyć tylko wartość właściwości w przypadku braku wyższej wartości pierwszeństwa .

Ważne

Dokumentacja przewodnika dla komputerów dla platform .NET 7 i .NET 6 jest w budowie.

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.

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żności jest propagowana z elementu nadrzędnego do elementów podrzędnych w drzewie elementów zawierających właściwość . W adiustacji 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. AllowDrop Ponieważ właściwość zależności dla canvas1 właściwości jest ustawiona na true, element potomny stackPanel1 i label1 elementy dziedziczą true jako ich AllowDrop wartość.

<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 działa na wynikowym drzewie obiektów. W poniższym przykładzie stackPanel2 element jest dodawany do kolekcji podrzędnej elementu canvas2. label2 Podobnie element jest dodawany do kolekcji podrzędnej stackPanel2elementu . AllowDrop Ponieważ właściwość zależności dla canvas2 właściwości jest ustawiona na true, element potomny stackPanel2 i label2 elementy dziedziczą true jako ich AllowDrop wartość.

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 na właściwościach zależności, dla których jest wygodne dla użytkownika ustawienie wartości właściwości raz w elemecie nadrzędnym i że wartość właściwości jest propagowana do elementów potomnych w drzewie elementów podrzędnych.

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 elementów tekstu i podrzędnego interfejsu użytkownika w elemecie 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 metadanychFlowDirectionwłaściwości , wartość musi być ustawiona tylko raz w górnej części drzewa elementów dla strony. W rzadkich przypadkach, gdy dla strony jest przeznaczona kombinacja wskazówek przepływu, można ustawić inny kierunek przepływu na elemenie 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 właściwości niestandardowej dziedziczonej

Właściwość zależności niestandardowej można dziedziczyć, włączając Inherits właściwość w wystąpieniu FrameworkPropertyMetadataklasy , a następnie rejestrując niestandardową właściwość zależności w tym wystąpieniu metadanych. Domyślnie Inherits wartość jest ustawiona na wartość w elemFrameworkPropertyMetadata.false 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 RegisterAttached metody zgodnie z Inherits opisem w sekcji Rejestrowanie dołączonej właściwości. 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łączoną Inherits wartością i wartością falsedomyślną . Przykład zawiera również otokę właściwości z metodami get i set metodami dostępu.

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 drzewa 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

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 właściwości przy użyciu polecenia RegisterAttached.

Zobacz też