Ereditarietà del valore della proprietà (WPF .NET)
L'ereditarietà del valore della proprietà è una funzionalità del sistema di proprietà Windows Presentation Foundation (WPF) e si applica alle proprietà di dipendenza. L'ereditarietà del valore della proprietà consente agli elementi figlio in un albero di elementi di ottenere il valore di una determinata proprietà dall'elemento padre più vicino. Poiché un elemento padre potrebbe anche aver ottenuto il valore della proprietà attraverso l'ereditarietà dei valori delle proprietà, il sistema potrebbe quindi tornare fino alla radice della pagina.
Il sistema di proprietà WPF non abilita l'ereditarietà del valore della proprietà per impostazione predefinita e l'ereditarietà dei valori è inattiva, a meno che non sia abilitata specificamente nei metadati della proprietà di dipendenza . Anche se l'ereditarietà del valore della proprietà è abilitata, un elemento figlio erediterà solo un valore della proprietà in assenza di un valore precedenza superiore valore.
Prerequisiti
L'articolo presuppone una conoscenza di base delle proprietà di dipendenza e che tu abbia letto la panoramica delle proprietà di dipendenza. Per seguire gli esempi in questo articolo, è utile se si ha familiarità con Extensible Application Markup Language (XAML) e si sa come scrivere applicazioni WPF.
Ereditarietà tramite un albero di elementi
L'ereditarietà del valore della proprietà non è lo stesso concetto dell'ereditarietà della classe nella programmazione orientata agli oggetti, in cui le classi derivate ereditano membri della classe base. Questo tipo di ereditarietà è attivo anche in WPF, anche se in XAML le proprietà della classe di base ereditate vengono esposte come attributi di elementi XAML che rappresentano classi derivate.
L'ereditarietà del valore di una proprietà di dipendenza è il meccanismo in base al quale il valore di una proprietà di dipendenza viene propagato dagli elementi padre a quelli figlio all'interno di un albero di elementi che contengono la proprietà. Nel markup XAML un albero di elementi è visibile come elementi annidati.
L'esempio seguente mostra gli elementi annidati in XAML. WPF registra la proprietà di dipendenza AllowDrop nella classe UIElement con i metadati della proprietà che abilitano l'ereditarietà del valore della proprietà e imposta il valore predefinito su false
. La proprietà di dipendenza AllowDrop
esiste negli elementi Canvas, StackPanele Label poiché derivano tutti da UIElement
. Poiché la proprietà di dipendenza AllowDrop
per canvas1
è impostata su true
, gli elementi discendenti stackPanel1
e label1
ereditano true
come valore 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>
È anche possibile creare un albero di elementi a livello di codice aggiungendo elementi alla raccolta di elementi figlio di un altro elemento. In fase di esecuzione, l'ereditarietà del valore della proprietà opera sull'albero degli oggetti risultante. Nell'esempio seguente stackPanel2
viene aggiunto alla raccolta figlio di canvas2
. Analogamente, label2
viene aggiunto alla raccolta dei figli di stackPanel2
. Poiché la proprietà di dipendenza AllowDrop su canvas2
è impostata su true
, gli elementi discendenti stackPanel2
e label2
ereditano true
come loro valore 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)
Applicazioni pratiche di ereditarietà dei valori di proprietà
Le proprietà di dipendenza WPF specifiche hanno l'ereditarietà dei valori abilitata per impostazione predefinita, ad esempio AllowDrop e FlowDirection. In genere, le proprietà con ereditarietà dei valori abilitate per impostazione predefinita vengono implementate nelle classi degli elementi dell'interfaccia utente di base, in modo che esistano nelle classi derivate. Ad esempio, poiché AllowDrop
viene implementato nella classe base UIElement, tale proprietà di dipendenza esiste anche in ogni controllo derivato da UIElement
. WPF abilita l'ereditarietà dei valori nelle proprietà di dipendenza per le quali un utente può impostare il valore della proprietà una sola volta su un elemento padre e propagare tale valore di proprietà agli elementi discendenti nell'albero degli elementi.
Il modello di ereditarietà del valore delle proprietà assegna i valori delle proprietà, sia ereditati che non ereditati, in base alla precedenza dei valori delle proprietà dipendenti secondo il modello . Pertanto, un valore della proprietà dell'elemento padre verrà applicato solo a un elemento figlio, se la proprietà dell'elemento figlio non ha un valore di precedenza superiore, ad esempio un valore impostato localmente o un valore ottenuto tramite stili, modelli o data binding.
La proprietà di dipendenza FlowDirection imposta la direzione del layout degli elementi di testo e dell'interfaccia utente figlio all'interno di un elemento padre. In genere, si prevede che la direzione del flusso degli elementi di testo e interfaccia utente all'interno di una pagina sia coerente. Poiché l'ereditarietà dei valori è abilitata nella proprietà metadati di FlowDirection
, è necessario impostare un valore una sola volta nella parte superiore dell'albero degli elementi per una pagina. Nel raro caso in cui una combinazione di direzioni di flusso sia destinata a una pagina, è possibile impostare una direzione di flusso diversa su un elemento dell'albero assegnando un valore impostato localmente. La nuova direzione del flusso verrà quindi propagata agli elementi discendenti al di sotto di tale livello.
Rendere ereditabile una proprietà personalizzata
È possibile rendere ereditabile una proprietà di dipendenza personalizzata abilitando la proprietà Inherits in un'istanza di FrameworkPropertyMetadatae quindi registrando la proprietà di dipendenza personalizzata con tale istanza di metadati. Per impostazione predefinita, Inherits
è impostato su false
in FrameworkPropertyMetadata
. Rendere ereditabile un valore di proprietà influisce sulle prestazioni, quindi impostare Inherits
su true
solo se tale funzionalità è necessaria.
Quando si registra una proprietà di dipendenza con Inherits
abilitata nei metadati, usare il metodo RegisterAttached come descritto in Registrare una proprietà associata. Assegnare inoltre un valore predefinito alla proprietà in modo che esista un valore ereditabile. È anche possibile creare un wrapper di proprietà con metodi di accesso get
e set
sul tipo di proprietario, proprio come per una proprietà di dipendenza non collegata. In questo modo è possibile impostare il valore della proprietà usando il wrapper della proprietà in un tipo proprietario o derivato. Nell'esempio seguente viene creata una proprietà di dipendenza denominata IsTransparent
, con Inherits
abilitato e un valore predefinito di false
. L'esempio include anche un wrapper di proprietà con get
e set
funzioni di accesso.
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
Le proprietà associate sono concettualmente simili alle proprietà globali. È possibile controllarne il valore in qualsiasi DependencyObject e ottenere un risultato valido. Lo scenario tipico per le proprietà associate consiste nell'impostare i valori delle proprietà sugli elementi figlio e tale scenario è più efficace se la proprietà in questione è implicitamente presente come proprietà associata per ogni elemento DependencyObject nell'albero.
Ereditare i valori delle proprietà attraverso i confini dell'albero
L'ereditarietà delle proprietà funziona attraversando un albero di elementi. Questo albero è spesso parallelo all'albero logico. Tuttavia, ogni volta che si include un oggetto a livello di core WPF, ad esempio un Brush, nel markup che definisce un albero degli elementi, è stato creato un albero logico discontinuo. Un vero albero logico non si estende concettualmente attraverso il Brush
, perché l'albero logico è un concetto a livello di framework WPF. È possibile usare i metodi helper di LogicalTreeHelper per analizzare e visualizzare l'estensione di un albero logico. L'ereditarietà dei valori delle proprietà è in grado di trasmettere valori attraverso un albero logico discontinuo, ma solo se la proprietà ereditabile è stata registrata come proprietà associata e non esiste un confine intenzionale che blocca l'ereditarietà, come ad esempio un Frame.
Nota
Anche se l'ereditarietà dei valori di proprietà potrebbe funzionare per le proprietà di dipendenza non associate, il comportamento di ereditarietà per una proprietà non associata attraverso alcuni limiti di elemento nell'albero di runtime non è definito. Ogni volta che specifichi Inherits nei metadati delle proprietà, registra le proprietà usando RegisterAttached.
Vedere anche
.NET Desktop feedback