Panoramica delle proprietà associate (WPF .NET)

Una proprietà associata è un concetto XAML (Extensible Application Markup Language). Le proprietà associate consentono di impostare coppie proprietà/valore aggiuntive su qualsiasi elemento XAML che deriva da DependencyObject, anche se l'elemento non definisce tali proprietà aggiuntive nel modello a oggetti. Le proprietà aggiuntive sono accessibili a livello globale. Le proprietà associate vengono in genere definite come una forma specializzata di proprietà di dipendenza che non dispone di un wrapper di proprietà convenzionale.

Importante

La documentazione di Desktop Guide per .NET 7 e .NET 6 è in fase di costruzione.

Prerequisiti

L'articolo presuppone una conoscenza di base delle proprietà di dipendenza e che si abbia letto Panoramica delle proprietà di dipendenza. Per seguire gli esempi in questo articolo, è utile se si ha familiarità con XAML e si sa come scrivere applicazioni Windows Presentation Foundation (WPF).

Perché usare le proprietà associate

Una proprietà associata consente a un elemento figlio di specificare un valore univoco per una proprietà definita in un elemento padre. Uno scenario comune è un elemento figlio che specifica come deve essere sottoposto a rendering nell'interfaccia utente dall'elemento padre. Ad esempio, DockPanel.Dock è una proprietà associata perché è impostata su elementi figlio di un DockPaneloggetto , non su DockPanel se stesso. La DockPanel classe definisce un campo statico DependencyProperty , denominato DockPropertye quindi fornisce GetDock metodi e SetDock come funzioni di accesso pubbliche per la proprietà associata.

Proprietà associate in XAML

In XAML, imposti le proprietà associate usando la sintassi <attached property provider type>.<property name>, dove il provider di proprietà associato è la classe che definisce la proprietà associata. Nell'esempio seguente viene illustrato come un elemento figlio di DockPanel può impostare il valore della DockPanel.Dock proprietà.

<DockPanel>
    <TextBox DockPanel.Dock="Top">Enter text</TextBox>
</DockPanel>

L'utilizzo è simile a una proprietà statica in cui si fa riferimento al tipo proprietario e registra la proprietà associata (ad esempio, DockPanel), non il nome dell'istanza.

Quando specifichi una proprietà associata usando un attributo XAML, è applicabile solo l'azione impostata. Non è possibile ottenere direttamente un valore della proprietà tramite XAML, anche se esistono alcuni meccanismi indiretti per confrontare i valori, ad esempio i trigger negli stili.

Proprietà associate in WPF

Le proprietà associate sono un concetto XAML, le proprietà di dipendenza sono un concetto WPF. In WPF la maggior parte delle proprietà associate correlate all'interfaccia utente sui tipi WPF viene implementata come proprietà di dipendenza. Le proprietà associate WPF implementate come proprietà di dipendenza supportano concetti relativi alle proprietà di dipendenza, ad esempio i metadati delle proprietà, inclusi i valori predefiniti dei metadati.

Modelli di utilizzo delle proprietà associate

Anche se qualsiasi oggetto può impostare un valore di proprietà associata, ciò non significa che l'impostazione di un valore produrrà un risultato tangibile o il valore verrà usato da un altro oggetto. Lo scopo principale delle proprietà associate è fornire un modo per gli oggetti di un'ampia gamma di gerarchie di classi e relazioni logiche per segnalare informazioni comuni al tipo che definisce la proprietà associata. L'utilizzo delle proprietà associate segue in genere uno di questi modelli:

  • Il tipo che definisce la proprietà associata è l'elemento padre degli elementi che impostano i valori per la proprietà associata. Il tipo padre esegue l'iterazione dei relativi oggetti figlio tramite logica interna che agisce sulla struttura ad albero di oggetti, ottiene i valori e agisce in qualche modo su tali valori.
  • Il tipo che definisce la proprietà associata viene utilizzato come elemento figlio per vari elementi padre e con modalità tenda ls.
  • Il tipo che definisce la proprietà associata rappresenta un servizio. Gli altri tipi impostano i valori per la proprietà associata. Pertanto, quando l'elemento che imposta la proprietà viene valutato nel contesto del servizio, i valori della proprietà associata vengono ottenuti tramite la logica interna della classe del servizio.

Esempio di proprietà associata definita dall'elemento padre

Lo scenario tipico in cui WPF definisce una proprietà associata è quando un elemento padre supporta una raccolta di elementi figlio e l'elemento padre implementa un comportamento basato sui dati segnalati da ognuno dei relativi elementi figlio.

DockPanel definisce la DockPanel.Dock proprietà associata. DockPanel dispone di codice a livello di classe, in particolare MeasureOverride e ArrangeOverride, che fa parte della logica di rendering. Un'istanza DockPanel controlla se uno dei relativi elementi figlio immediati ha impostato un valore per DockPanel.Dock. In tal caso, questi valori diventano input per la logica di rendering applicata a ogni elemento figlio. Sebbene sia teoricamente possibile che le proprietà associate influisca sugli elementi oltre l'elemento padre immediato, il comportamento definito per un'istanza annidata DockPanel consiste nell'interagire solo con la raccolta immediata di elementi figlio. Pertanto, se si imposta DockPanel.Dock su un elemento senza DockPanel elemento padre, non verrà generato alcun errore o eccezione e si sarebbe creato un valore di proprietà globale che non verrà utilizzato da alcun DockPaneloggetto .

Proprietà associate nel codice

Le proprietà associate in WPF non hanno i metodi CLR get e set wrapper tipici perché le proprietà potrebbero essere impostate dall'esterno dello spazio dei nomi CLR. Per consentire a un processore XAML di impostare tali valori durante l'analisi di XAML, la classe che definisce la proprietà associata deve implementare metodi di accesso dedicati sotto forma di Get<property name> e Set<property name>.

È anche possibile usare i metodi della funzione di accesso dedicati per ottenere e impostare una proprietà associata nel codice, come illustrato nell'esempio seguente. Nell'esempio è myTextBox un'istanza della TextBox classe .

DockPanel myDockPanel = new();
TextBox myTextBox = new();
myTextBox.Text = "Enter text";

// Add child element to the DockPanel.
myDockPanel.Children.Add(myTextBox);

// Set the attached property value.
DockPanel.SetDock(myTextBox, Dock.Top);
Dim myDockPanel As DockPanel = New DockPanel()
Dim myTextBox As TextBox = New TextBox()
myTextBox.Text = "Enter text"

' Add child element to the DockPanel.
myDockPanel.Children.Add(myTextBox)

' Set the attached property value.
DockPanel.SetDock(myTextBox, Dock.Top)

Se non si aggiunge myTextBox come elemento figlio di myDockPanel, la chiamata SetDock non genererà un'eccezione o avrà alcun effetto. Solo un DockPanel.Dock valore impostato su un elemento figlio di un DockPanel oggetto può influire sul rendering e il rendering sarà lo stesso se si imposta il valore prima o dopo l'aggiunta dell'elemento figlio a DockPanel.

Dal punto di vista del codice, una proprietà associata è simile a un campo sottostante con funzioni di accesso al metodo anziché alle funzioni di accesso alle proprietà e può essere impostato su qualsiasi oggetto senza dover prima essere definito su tali oggetti.

Metadati delle proprietà associate

I metadati per una proprietà associata in genere non sono diversi da quelli di una proprietà di dipendenza. Quando si registra una proprietà associata, utilizzare FrameworkPropertyMetadata per specificare le caratteristiche della proprietà, ad esempio se la proprietà influisce sul rendering o sulla misurazione. Quando si specifica un valore predefinito eseguendo l'override dei metadati delle proprietà associate, tale valore diventa l'impostazione predefinita per la proprietà associata implicita nelle istanze della classe di override. Se un valore della proprietà associata non è impostato in altro modo, il valore predefinito viene segnalato quando viene eseguita una query sulla proprietà usando la Get<property name> funzione di accesso con un'istanza della classe in cui sono stati specificati i metadati.

Per abilitare l'ereditarietà dei valori di proprietà in una proprietà, utilizzare proprietà associate anziché proprietà di dipendenza non associate. Per altre informazioni, vedere Ereditarietà dei valori delle proprietà.

Proprietà associate personalizzate

Quando creare una proprietà associata

La creazione di una proprietà associata è utile quando:

  • È necessario un meccanismo di impostazione delle proprietà disponibile per le classi diverse dalla classe di definizione. Uno scenario comune riguarda il layout dell'interfaccia utente, ad esempio DockPanel.Dock, Panel.ZIndexe Canvas.Top sono tutti esempi di proprietà di layout esistenti. Nello scenario di layout, gli elementi figlio di un elemento di controllo del layout sono in grado di esprimere i requisiti di layout al relativo elemento padre di layout e di impostare un valore per una proprietà associata definita dall'elemento padre.

  • Una delle classi rappresenta un servizio e si vuole che altre classi integrino il servizio in modo più trasparente.

  • Si vuole il supporto di Progettazione WPF di Visual Studio, ad esempio la possibilità di modificare una proprietà tramite la finestra Proprietà . Per altre informazioni, vedere Cenni preliminari sulla creazione di controlli.

  • Si vuole usare l'ereditarietà del valore della proprietà.

Come creare una proprietà associata

Se la classe definisce una proprietà associata esclusivamente per l'uso da parte di altri tipi, la classe non deve derivare da DependencyObject. In caso contrario, seguire il modello WPF di avere una proprietà associata anche come proprietà di dipendenza, derivando la classe da DependencyObject.

Definire la proprietà associata come dipendenza nella classe di definizione dichiarando un public static readonly campo di tipo DependencyProperty. Assegnare quindi il valore restituito del RegisterAttached metodo al campo , noto anche come identificatore della proprietà di dipendenza. Seguire la convenzione di denominazione delle proprietà WPF che distingue i campi dalle proprietà che rappresentano, assegnando un nome al campo <property name>Propertyidentificatore . Fornire inoltre metodi statici Get<property name> e Set<property name> di accesso, che consentono al sistema di proprietà di accedere alla proprietà associata.

Nell'esempio seguente viene illustrato come registrare una proprietà di dipendenza usando il RegisterAttached metodo e come definire i metodi della funzione di accesso. Nell'esempio il nome della proprietà associata è HasFish, quindi il campo dell'identificatore è denominato HasFishPropertye i metodi della funzione di accesso sono denominati GetHasFish e SetHasFish.

public class Aquarium : UIElement
{
    // Register an attached dependency property with the specified
    // property name, property type, owner type, and property metadata.
    public static readonly DependencyProperty HasFishProperty = 
        DependencyProperty.RegisterAttached(
      "HasFish",
      typeof(bool),
      typeof(Aquarium),
      new FrameworkPropertyMetadata(defaultValue: false,
          flags: FrameworkPropertyMetadataOptions.AffectsRender)
    );

    // Declare a get accessor method.
    public static bool GetHasFish(UIElement target) =>
        (bool)target.GetValue(HasFishProperty);

    // Declare a set accessor method.
    public static void SetHasFish(UIElement target, bool value) =>
        target.SetValue(HasFishProperty, value);
}
Public Class Aquarium
    Inherits UIElement

    ' Register an attached dependency property with the specified
    ' property name, property type, owner type, and property metadata.
    Public Shared ReadOnly HasFishProperty As DependencyProperty =
        DependencyProperty.RegisterAttached("HasFish", GetType(Boolean), GetType(Aquarium),
            New FrameworkPropertyMetadata(defaultValue:=False,
                flags:=FrameworkPropertyMetadataOptions.AffectsRender))

    ' Declare a get accessor method.
    Public Shared Function GetHasFish(target As UIElement) As Boolean
        Return target.GetValue(HasFishProperty)
    End Function

    ' Declare a set accessor method.
    Public Shared Sub SetHasFish(target As UIElement, value As Boolean)
        target.SetValue(HasFishProperty, value)
    End Sub

End Class

Funzione di accesso Get

La firma del get metodo di accesso è public static object Get<property name>(DependencyObject target), dove:

  • target è l'oggetto DependencyObject da cui viene letta la proprietà associata. Il target tipo può essere più specifico di DependencyObject. Ad esempio, il metodo della DockPanel.GetDock funzione di accesso digita target come UIElement perché la proprietà associata deve essere impostata nelle UIElement istanze di . UiElement indirettamente deriva da DependencyObject.
  • Il tipo restituito può essere più specifico di object. Ad esempio, il GetDock metodo digita il valore restituito come Dock perché il valore restituito deve essere un'enumerazione Dock .

Nota

La get funzione di accesso per una proprietà associata è necessaria per il supporto del data binding negli strumenti di progettazione, ad esempio Visual Studio o Blend per Visual Studio.

Funzione di accesso Set

La firma del set metodo di accesso è public static void Set<property name>(DependencyObject target, object value), dove:

  • target è l'oggetto DependencyObject in cui viene scritta la proprietà associata. Il target tipo può essere più specifico di DependencyObject. Ad esempio, il SetDock metodo digita target come UIElement perché la proprietà associata deve essere impostata nelle UIElement istanze di . UiElement indirettamente deriva da DependencyObject.
  • Il value tipo può essere più specifico di object. Ad esempio, il SetDock metodo richiede un Dock valore. Il caricatore XAML deve essere in grado di generare il value tipo dalla stringa di markup che rappresenta il valore della proprietà associata. Pertanto, deve essere presente il supporto per la conversione dei tipi, il serializzatore di valori o il supporto dell'estensione di markup per il tipo usato.

Attributi delle proprietà associate

WPF definisce diversi attributi .NET che forniscono informazioni sulle proprietà associate ai processi di reflection e anche ai consumer di informazioni sulla reflection e sulle proprietà, ad esempio le finestre di progettazione. I progettisti usano attributi .NET definiti da WPF per limitare le proprietà visualizzate nella finestra delle proprietà, per evitare di sovraccaricare gli utenti con un elenco globale di tutte le proprietà associate. È possibile applicare questi attributi alle proprietà associate personalizzate. Lo scopo e la sintassi degli attributi .NET sono descritti in queste pagine di riferimento:

Altre informazioni

  • Per altre informazioni sulla creazione di una proprietà associata, vedere Registrare una proprietà associata.
  • Per scenari di utilizzo più avanzati per le proprietà di dipendenza e le proprietà associate, vedere Proprietà di dipendenza personalizzate.
  • È possibile registrare una proprietà sia come proprietà associata che come proprietà di dipendenza e includere wrapper di proprietà convenzionali. In questo modo, una proprietà può essere impostata su un elemento usando wrapper di proprietà e anche su qualsiasi altro elemento usando la sintassi della proprietà associata XAML. Per un esempio, vedere FrameworkElement.FlowDirection.

Vedi anche