Condividi tramite


Panoramica delle proprietà allegate

Una proprietà associata è un concetto definito da XAML. Una proprietà associata deve essere utilizzata come tipo di proprietà globale che può essere impostata su qualsiasi oggetto dipendente. In Windows Presentation Foundation (WPF), le proprietà associate vengono in genere definite come una forma specializzata di proprietà di dipendenza che non dispone della proprietà convenzionale "wrapper".

Prerequisiti

Questo articolo presuppone che tu comprenda le proprietà di dipendenza dal punto di vista di un utente di proprietà di dipendenza esistenti nelle classi di Windows Presentation Foundation (WPF) e che tu abbia letto l'articolo Panoramica sulle proprietà di dipendenza. Per seguire gli esempi in questo articolo, è necessario comprendere anche XAML e sapere come scrivere applicazioni WPF.

Perché usare le proprietà associate

Uno degli scopi di una proprietà associata è consentire a diversi elementi figlio di specificare valori univoci per una proprietà definita in un elemento padre. Un'applicazione specifica di questo scenario è che gli elementi figlio informano l'elemento padre su come devono essere presentati nell'interfaccia utente (UI). Un esempio è la proprietà DockPanel.Dock. La proprietà DockPanel.Dock viene creata come proprietà associata perché è progettata per essere impostata su elementi contenuti all'interno di un DockPanel anziché su DockPanel stesso. La classe DockPanel definisce il campo DependencyProperty statico denominato DockPropertye quindi fornisce i metodi GetDock e SetDock come funzioni di accesso pubbliche per la proprietà associata.

Proprietà associate in XAML

In XAML le proprietà associate vengono impostate usando la sintassi AttachedPropertyProvider.PropertyName

Di seguito è riportato un esempio di come impostare DockPanel.Dock in XAML:

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

L'uso è in una certa misura simile a quello di una proprietà statica; si fa sempre riferimento al tipo DockPanel che possiede e registra la proprietà allegata, piuttosto che fare riferimento a qualsiasi istanza specificata dal nome.

Inoltre, poiché una proprietà associata in XAML è un attributo impostato nel markup, solo l'operazione impostata ha rilevanza. Non è possibile ottenere direttamente una proprietà in XAML, anche se esistono alcuni meccanismi indiretti per confrontare valori, come ad esempio i trigger negli stili (per informazioni dettagliate, vedi Stili e Modellazione).

Implementazione delle proprietà associate in WPF

In Windows Presentation Foundation (WPF) la maggior parte delle proprietà associate all'interfaccia utente sui tipi WPF viene implementata come proprietà di dipendenza. Le proprietà associate sono un concetto XAML, mentre le proprietà di dipendenza sono un concetto WPF. Poiché le proprietà allegate di WPF sono proprietà di dipendenza, supportano concetti come i metadati delle proprietà e i valori predefiniti derivati da quei metadati delle proprietà.

Modalità di utilizzo delle proprietà associate da parte del tipo proprietario

Anche se le proprietà associate sono impostabili in qualsiasi oggetto, ciò non significa automaticamente che l'impostazione della proprietà produrrà un risultato tangibile o che il valore verrà mai utilizzato da un altro oggetto. In genere, le proprietà associate sono concepite in modo che gli oggetti provenienti da un'ampia gamma di gerarchie di classi o relazioni logiche possano segnalare informazioni comuni al tipo che definisce la proprietà associata. Il tipo che definisce la proprietà associata segue in genere uno di questi modelli:

  • Il tipo che definisce la proprietà associata è progettato in modo che possa essere l'elemento padre degli elementi che impostano i valori per la proprietà associata. Il tipo esegue quindi l'iterazione degli oggetti figlio tramite logica interna in base a una struttura ad albero di oggetti, ottiene i valori e agisce in qualche modo su tali valori.

  • Il tipo che definisce la proprietà associata verrà utilizzato come elemento figlio per un'ampia gamma di possibili elementi padre e modelli di contenuto.

  • Il tipo che definisce la proprietà associata rappresenta un servizio. Altri tipi impostano i valori per la proprietà collegata. Quindi, quando l'elemento che imposta la proprietà viene valutato nel contesto del servizio, i valori delle proprietà associate vengono ottenuti tramite la logica interna della classe del servizio.

Esempio di una proprietà associata Parent-Defined

Lo scenario più tipico in cui WPF definisce una proprietà associata è quando un elemento padre supporta una raccolta di elementi figlio e implementa anche un comportamento in cui le specifiche del comportamento vengono segnalate singolarmente per ogni elemento figlio.

DockPanel definisce la proprietà associata DockPanel.Dock e DockPanel include codice a livello di classe come parte della logica di rendering (in particolare, MeasureOverride e ArrangeOverride). Un'istanza di DockPanel verificherà sempre se uno dei suoi elementi figli immediati ha impostato un valore per DockPanel.Dock. In tal caso, questi valori diventano input per la logica di rendering applicata a tale particolare elemento figlio. Le istanze di DockPanel annidate gestiscono ognuna le proprie raccolte di elementi figlio immediati, ma questo comportamento è specifico dell'implementazione a seconda di come DockPanel elabora i valori di DockPanel.Dock. È teoricamente possibile avere proprietà associate che influenzano gli elementi oltre l'elemento padre immediato. Se la proprietà associata DockPanel.Dock è impostata su un elemento che non dispone di DockPanel elemento padre da agire su di esso, non viene generato alcun errore o eccezione. Ciò significa semplicemente che è stato impostato un valore di proprietà globale, ma non dispone di un DockPanel padre corrente che potrebbe utilizzare le informazioni.

Proprietà associate nel codice

Le proprietà associate in WPF non dispongono dei metodi CLR "wrapper" tipici per facilitare l'accesso tramite get/set. Ciò è dovuto al fatto che la proprietà associata non fa necessariamente parte dello spazio dei nomi CLR per le istanze in cui è impostata la proprietà. Tuttavia, un processore XAML deve essere in grado di impostare tali valori quando XAML viene analizzato. Per supportare un utilizzo efficace delle proprietà associate, il tipo di proprietario della proprietà associata deve implementare metodi di accesso dedicati nel formato GetPropertyName e SetPropertyName. Questi metodi di accesso dedicati sono utili anche per ottenere o impostare la proprietà associata nel codice. Dal punto di vista del codice, una proprietà associata è simile a un campo sottostante con funzioni di accesso al metodo invece delle funzioni di accesso alle proprietà e tale campo sottostante può esistere in qualsiasi oggetto anziché dover essere definito in modo specifico.

Nell'esempio seguente viene illustrato come impostare una proprietà associata nel codice. In questo esempio, myCheckBox è un'istanza della classe CheckBox.

DockPanel myDockPanel = new DockPanel();
CheckBox myCheckBox = new CheckBox();
myCheckBox.Content = "Hello";
myDockPanel.Children.Add(myCheckBox);
DockPanel.SetDock(myCheckBox, Dock.Top);
Dim myDockPanel As New DockPanel()
Dim myCheckBox As New CheckBox()
myCheckBox.Content = "Hello"
myDockPanel.Children.Add(myCheckBox)
DockPanel.SetDock(myCheckBox, Dock.Top)

Analogamente al caso XAML, se myCheckBox non fosse già stato aggiunto come elemento figlio di myDockPanel dalla quarta riga di codice, la quinta riga di codice non genererà un'eccezione, ma il valore della proprietà non interagirà con un elemento padre DockPanel e quindi non eseguirà alcuna operazione. Solo un valore DockPanel.Dock impostato su un elemento figlio combinato con la presenza di un elemento padre DockPanel causerà un comportamento efficace nell'applicazione sottoposta a rendering. In questo caso, è possibile impostare la proprietà associata, quindi collegarsi all'albero. In alternativa, è possibile collegarsi all'albero e quindi impostare la proprietà associata. Entrambi gli ordini di azione forniscono lo stesso risultato.

dei metadati delle proprietà associate

Quando si registra la proprietà, FrameworkPropertyMetadata viene impostato per specificare le caratteristiche della proprietà, ad esempio se la proprietà influisce sul rendering, la misurazione e così via. I metadati per una proprietà associata in genere non sono diversi da quelli di una proprietà di dipendenza. Se si specifica un valore predefinito in un override per i metadati delle proprietà attaccate, tale valore diventa il valore predefinito della proprietà attaccata implicita nelle istanze della classe che effettua l'override. In particolare, il valore predefinito viene segnalato se un processo interroga il valore di una proprietà associata tramite il metodo di accesso Get per quella proprietà, specificando un'istanza della classe in cui hai specificato i metadati, e il valore per quella proprietà associata non è stato altrimenti impostato.

Se si desidera abilitare l'ereditarietà del valore della proprietà in una proprietà, è consigliabile usare proprietà associate anziché proprietà di dipendenza non associate. Per informazioni dettagliate, consultare l'ereditarietà del valore della proprietà nella sezione .

Proprietà associate personalizzate

Quando creare una proprietà associata

È possibile creare una proprietà associata quando esiste un motivo per cui è disponibile un meccanismo di impostazione delle proprietà per le classi diverse dalla classe di definizione. Lo scenario più comune per questo è quello del layout. Esempi di proprietà di layout esistenti sono DockPanel.Dock, Panel.ZIndexe Canvas.Top. Lo scenario abilitato qui prevede che gli elementi che esistono come elementi figlio degli elementi di controllo del layout possano esprimere individualmente i requisiti di layout ai loro elementi padre, ognuno impostando un valore di proprietà definito dal padre come proprietà associata.

Un altro scenario per l'uso di una proprietà associata è quando la classe rappresenta un servizio e si vuole che le classi siano in grado di integrare il servizio in modo più trasparente.

Un altro scenario consiste nel ricevere il supporto di Progettazione WPF di Visual Studio, ad esempio la modifica della finestra Proprietà . Per altre informazioni, vedere Cenni preliminari sulla creazione di controlli.

Come accennato in precedenza, è necessario registrarsi come proprietà associata se si desidera utilizzare l'ereditarietà del valore della proprietà.

Come creare una proprietà associata

Se la classe definisce rigorosamente la proprietà associata per l'uso su altri tipi, la classe non deve derivare da DependencyObject. Tuttavia, è necessario derivare da DependencyObject se si segue il modello WPF complessivo di avere la proprietà associata anche come proprietà di dipendenza.

Definire la proprietà associata come proprietà di dipendenza dichiarando un campo public static readonly di tipo DependencyProperty. Questo campo viene definito usando il valore restituito del metodo RegisterAttached. Il nome del campo deve corrispondere al nome della proprietà associata, aggiunto alla stringa Property, per seguire il modello WPF stabilito di denominazione dei campi di identificazione rispetto alle proprietà rappresentate. Il provider di proprietà associato deve inoltre fornire metodi statici GetPropertyName e SetPropertyName come funzioni di accesso per la proprietà associata; in caso contrario, il sistema di proprietà non sarà in grado di utilizzare la vostra proprietà associata.

Nota

Se si omette il metodo get della proprietà associata, il data binding sulla proprietà non funzionerà negli ambienti di sviluppo, come Visual Studio e Blend per Visual Studio.

Funzione di accesso Get

La firma per la funzione di accesso GetPropertyName deve essere:

public static object GetPropertyName(object target)

  • L'oggetto target può essere specificato come tipo più specifico nell'implementazione. Ad esempio, il metodo DockPanel.GetDock digita il parametro come UIElement, perché la proprietà associata deve essere impostata solo nelle istanze di UIElement.

  • Il valore restituito può essere specificato come tipo più specifico nell'implementazione. Ad esempio, il metodo GetDock lo digita come Dock, perché il valore può essere impostato solo su tale enumerazione.

Funzione di accesso Set

La firma per l'accessore SetPropertyName deve essere:

public static void SetPropertyName(object target, object value)

  • L'oggetto target può essere specificato come tipo più specifico nell'implementazione. Ad esempio, il metodo SetDock lo digita come UIElement, perché la proprietà associata deve essere impostata solo nelle istanze di UIElement.

  • L'oggetto value può essere specificato come tipo più specifico nell'implementazione. Ad esempio, il metodo SetDock lo digita come Dock, perché il valore può essere impostato solo su tale enumerazione. Tenere presente che il valore per questo metodo è l'input proveniente dal caricatore XAML quando rileva la proprietà associata in un utilizzo di proprietà associata nel markup. Tale input è il valore specificato come valore dell'attributo XAML nel markup. Pertanto, deve essere presente il supporto per la conversione del tipo, il serializzatore di valori o il supporto dell'estensione di markup per il tipo usato, in modo che il tipo appropriato possa essere creato dal valore dell'attributo (che in definitiva è solo una stringa).

Nell'esempio seguente viene illustrata la registrazione della proprietà di dipendenza (usando il metodo RegisterAttached), nonché i metodi di accesso Get PropertyName e Set PropertyName. Nell'esempio il nome della proprietà associata è IsBubbleSource. Pertanto, gli accessori devono essere denominati GetIsBubbleSource e SetIsBubbleSource.

public static readonly DependencyProperty IsBubbleSourceProperty = DependencyProperty.RegisterAttached(
  "IsBubbleSource",
  typeof(Boolean),
  typeof(AquariumObject),
  new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsRender)
);
public static void SetIsBubbleSource(UIElement element, Boolean value)
{
  element.SetValue(IsBubbleSourceProperty, value);
}
public static Boolean GetIsBubbleSource(UIElement element)
{
  return (Boolean)element.GetValue(IsBubbleSourceProperty);
}
Public Shared ReadOnly IsBubbleSourceProperty As DependencyProperty = DependencyProperty.RegisterAttached("IsBubbleSource", GetType(Boolean), GetType(AquariumObject), New FrameworkPropertyMetadata(False, FrameworkPropertyMetadataOptions.AffectsRender))
Public Shared Sub SetIsBubbleSource(ByVal element As UIElement, ByVal value As Boolean)
    element.SetValue(IsBubbleSourceProperty, value)
End Sub
Public Shared Function GetIsBubbleSource(ByVal element As UIElement) As Boolean
    Return CType(element.GetValue(IsBubbleSourceProperty), Boolean)
End Function

Attributi delle proprietà collegate

WPF definisce diversi attributi .NET destinati a fornire informazioni sulle proprietà associate nell'ambito dei processi di reflection e agli utenti tipici di reflection e informazioni sulle proprietà, come i designer. Poiché le proprietà associate hanno un tipo di ambito illimitato, i progettisti hanno bisogno di un modo per evitare di sovraccaricare gli utenti con un elenco globale di tutte le proprietà associate definite in una particolare implementazione tecnologica che usa XAML. Gli attributi .NET definiti da WPF per le proprietà associate possono essere usati per definire l'ambito delle situazioni in cui una determinata proprietà associata deve essere visualizzata in una finestra delle proprietà. Potresti considerare di applicare questi attributi anche alle tue proprietà associate personalizzate. Lo scopo e la sintassi degli attributi .NET sono descritti nelle pagine di riferimento appropriate:

Maggiori informazioni sulle proprietà associate

  • 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.

  • È anche possibile registrare una proprietà come proprietà associata e come proprietà di dipendenza, ma è comunque possibile esporre le implementazioni di "wrapper". In questo caso, la proprietà può essere impostata sia sull'elemento specifico, sia su qualsiasi elemento usando la sintassi della proprietà associata XAML. Un esempio di proprietà con uno scenario appropriato sia per gli utilizzi standard che per quelli associati è FrameworkElement.FlowDirection.

Vedere anche