Dziedziczenie wartości właściwości (WPF .NET)
Dziedziczenie wartości właściwości jest funkcją systemu 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 może również uzyskać wartość właściwości za pośrednictwem dziedziczenia wartości właściwości, system może być rekursją 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 włączone w metadanych właściwości zależności. Nawet po włączeniu dziedziczenia wartości właściwości element podrzędny będzie dziedziczyć wartość właściwości tylko w przypadku braku wartości o wyższym priorytecie .
Ważne
Dokumentacja przewodników klasycznych dla platform .NET 6 i .NET 5 (w tym .NET Core 3.1) jest w trakcie budowy.
Wymagania wstępne
W tym artykule przyjęto założenie, że masz podstawową wiedzę na temat właściwości zależności oraz że przeczytaliśmy artykuł Przegląd właściwości zależności. Aby postępować zgodnie z przykładami w tym artykule, warto zapoznać się z Extensible Application Markup Language (XAML) i dowiedzieć się, jak pisać aplikacje WPF.
Dziedziczenie za pośrednictwem drzewa elementów
Dziedziczenie wartości właściwości nie jest tym samym pojęciem co dziedziczenie klas w programowaniu obiektowym, gdzie klasy pochodne dziedziczą składowe klasy bazowej. Ten rodzaj dziedziczenia jest również aktywny w WPF, chociaż w XAML dziedziczone właściwości klasy bazowej są udostępniane 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 elementów nadrzędnych do podrzędnych w drzewie elementów, które zawierają właściwość . W znacznikach XAML drzewo elementów jest widoczne jako elementy zagnieżdżone.
W poniższym przykładzie pokazano zagnieżdżone elementy w języku XAML. WPF rejestruje właściwość AllowDrop zależności klasy za pomocą UIElement metadanych 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 dla elementów Canvas, StackPaneli , Label ponieważ wszystkie one pochodzą od .UIElement Ponieważ właściwość AllowDrop zależności w obiekcie jest canvas1 ustawiona na truewartość , elementy potomne stackPanel1label1 i 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 działania dziedziczenie wartości właściwości działa na wynikowym drzewie obiektów. W poniższym przykładzie jest stackPanel2 dodawany do kolekcji podrzędnejcanvas2. Podobnie jest label2 dodawany do kolekcji podrzędnej stackPanel2. Ponieważ właściwość AllowDrop zależności w obiekcie jest canvas2 ustawiona na truewartość , elementy potomne stackPanel2label2 i 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 włączonym dziedziczeniem wartości są domyślnie implementowane w podstawowych klasach elementów interfejsu użytkownika, więc istnieją w klasach pochodnych. Na przykład ponieważ klasa jest AllowDrop zaimplementowana w UIElement klasie bazowej, ta właściwość zależności istnieje również w każdej kontrolce pochodzącej z klasy UIElement. WPF umożliwia dziedziczenie wartości we właściwościach zależności, dla których użytkownik wygodnie ustawia wartość właściwości raz na elemencie nadrzędnym i ma propagację tej wartości właściwości do elementów potomnych w drzewie elementów.
Model dziedziczenia wartości właściwości przypisuje wartości właściwości, zarówno dziedziczone, jak i nieukońcowane, 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 lokalnie ustawiona wartość lub wartość uzyskana za pomocą stylów, szablonów lub powiązań danych.
Właściwość FlowDirection dependency ustawia kierunek układu tekstu i elementów podrzędnego interfejsu użytkownika w elemencie nadrzędnym. Zazwyczaj kierunek przepływu tekstu i elementów interfejsu użytkownika na stronie powinien być spójny. Ponieważ dziedziczenie wartości jest włączone w FlowDirectionmetadanych właściwości , wartość musi zostać ustawiona tylko raz w górnej części drzewa elementów dla strony. W rzadkich przypadkach, gdy dla strony jest przeznaczony mieszany kierunek przepływu, można ustawić inny kierunek przepływu dla elementu w drzewie, przypisując lokalnie ustawioną wartość. Nowy kierunek przepływu będzie następnie propagowany do elementów potomnych poniżej tego poziomu.
Zapewnianie dziedziczenia właściwości niestandardowej
Możesz ustawić niestandardową Inherits właściwość zależności jako dziedziczenie, włączając właściwość w wystąpieniu elementu , a FrameworkPropertyMetadatanastępnie rejestrując niestandardową właściwość zależności w tym wystąpieniu metadanych. Domyślnie wartość jest Inherits ustawiona na wartość w false .FrameworkPropertyMetadata Ustawienie wartości właściwości jako możliwej do dziedziczenia ma wpływ na wydajność, więc należy ustawić Inherits wartość na tylko true wtedy, gdy ta funkcja jest potrzebna.
Podczas rejestrowania właściwości zależności z włączoną Inherits właściwością w metadanych użyj RegisterAttached metody zgodnie z opisem w tece Register an attached property (Rejestrowanie dołączonej właściwości). Ponadto przypisz do właściwości wartość domyślną, aby istniała wartość dziedziczona. Możesz również utworzyć otokę get właściwości z obiektami i set accessors dla typu właściciela, podobnie jak w przypadku niedołąkowanej właściwości zależności. W ten sposób można ustawić wartość właściwości przy użyciu otoki właściwości właściciela lub typu pochodnego. Poniższy przykład tworzy właściwość zależności o nazwie IsTransparentz włączoną Inherits wartością domyślną false. Przykład zawiera również otokę właściwości z obiektami dostępu getset i .
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 z nich DependencyObject i uzyskać prawidłowy wynik. Typowy scenariusz dla dołączonych właściwości to ustawienie wartości właściwości dla elementów podrzędnych, a ten scenariusz jest bardziej efektywny, DependencyObject jeśli właściwość jest niejawnie obecna jako dołączona właściwość dla każdego elementu w drzewie.
Dziedziczenie wartości właściwości przez granice 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, Brushtaki jak , w znacznikach definiującym drzewo elementów, utworzone drzewo logiczne nie jest przerywane. Prawdziwe drzewo logiczne nie jest koncepcyjnie rozszerzane za pośrednictwem Brushobiektu , ponieważ drzewo logiczne jest koncepcją na poziomie platformy WPF. Za pomocą metod pomocników programu można LogicalTreeHelper analizować i wyświetlać zakres drzewa logicznego. Dziedziczenie wartości właściwości może przekazywać dziedziczone wartości za pośrednictwem przerywanego drzewa logicznego, ale tylko wtedy, gdy właściwość dziedziczona została zarejestrowana jako dołączona właściwość i nie istnieje celowa granica blokująca dziedziczenie, taka jak Frame.
Uwaga
Chociaż dziedziczenie wartości właściwości może wydawać się działać w przypadku niedołączonych właściwości zależności, zachowanie dziedziczenia dla niedołączonej właściwości przez granice niektórych elementów w drzewie środowiska uruchomieniowego jest niezdefiniowane. Zawsze, gdy określisz Inherits w metadanych właściwości, zarejestruj właściwości przy użyciu .RegisterAttached