Cenni preliminari sulle proprietà associate

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 dipendenza. 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 le proprietà di dipendenza siano comprensibili dal punto di vista di un consumer di proprietà di dipendenza esistenti nelle classi Windows Presentation Foundation (WPF) e che siano state lette le informazioni generali 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 elementi figlio diversi di specificare valori univoci per una proprietà definita in un elemento padre. Un'applicazione specifica di questo scenario include elementi figlio che informano l'elemento padre di come devono essere presentati nell'interfaccia utente. Un esempio è la DockPanel.Dock proprietà . La DockPanel.Dock proprietà viene creata come proprietà associata perché è progettata per essere impostata su elementi contenuti all'interno di un DockPanel oggetto anziché su DockPanel se stesso. La DockPanel classe definisce il campo statico DependencyProperty denominato DockPropertye quindi fornisce i GetDock metodi e SetDock come funzioni di accesso pubbliche per la proprietà associata.

Proprietà associate in XAML

In XAML, è possibile impostare le proprietà associate usando la sintassi ProviderProprietàAssociata.NomeProprietà

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

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

L'utilizzo è in qualche modo simile a una proprietà statica; si fa sempre riferimento al tipo DockPanel proprietario e registra la proprietà associata, anziché fare riferimento a qualsiasi istanza specificata dal nome.

Inoltre, dato che una proprietà associata in XAML è un attributo che viene impostato nel markup, solo l'operazione di impostazione ha una certa rilevanza. Non è possibile ottenere direttamente una proprietà in XAML, sebbene esistano alcuni meccanismi indiretti per confrontare i valori, ad esempio i trigger negli stili. Per altri dettagli, vedere Applicazione di stili e modelli.

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à associate WPF sono proprietà di dipendenza, supportano concetti relativi alle proprietà di dipendenza, ad esempio i metadati delle proprietà e i valori predefiniti dei metadati della proprietà.

Modalità di utilizzo delle proprietà associate dal tipo proprietario

Anche se le proprietà associate possono essere impostate per qualsiasi oggetto, ciò non significa che l'impostazione della proprietà produce un risultato tangibile o che il valore verrà usato da un altro oggetto. In genere, le proprietà associate sono concepite in modo che gli oggetti provenienti da un'ampia varietà di possibili gerarchie di classi o di relazioni logiche possano ciascuno riportare informazioni comuni al tipo che definisce la proprietà associata. Il tipo che definisce la proprietà associata si attiene di regola a uno di questi modelli:

  • Il tipo che definisce la proprietà associata è progettato in modo da poter essere l'elemento padre degli elementi che imposteranno i valori per la proprietà associata. Il tipo scorre quindi gli oggetti figlio attraverso la logica interna in base a una struttura ad albero degli oggetti, ottiene i valori e agisce in qualche modo su tali valori.

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

  • 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 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 DockPanel.Dock proprietà associata e DockPanel dispone di codice a livello di classe come parte della logica di rendering (in particolare, MeasureOverride e ArrangeOverride). Un'istanza DockPanel verificherà sempre se uno dei relativi elementi figlio immediati ha impostato un valore per DockPanel.Dock. In questo caso, tali valori diventano l'input per la logica di rendering applicata a quel particolare elemento figlio. Le istanze annidate DockPanel gestiscono le raccolte di elementi figlio immediate, ma questo comportamento è specifico dell'implementazione per l'elaborazione DockPanel dei DockPanel.Dock valori. In teoria, è possibile che alcune proprietà associate abbiano effetto su elementi più distanti dell'elemento padre immediato. Se la DockPanel.Dock proprietà associata è impostata su un elemento che non dispone di alcun DockPanel elemento padre per agire su di esso, non viene generato alcun errore o eccezione. Ciò significa semplicemente che è stato impostato un valore di proprietà globale, ma non ha un elemento padre corrente DockPanel 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 a 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 il codice 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 della funzione di accesso dedicati sono anche utili per ottenere o impostare la proprietà associata nel codice. Dal punto di vista del codice, una proprietà associata è simile a un campo sottostante che dispone di funzioni di accesso ai metodi anziché di funzioni di accesso alle proprietà e tale campo sottostante può trovarsi in qualsiasi oggetto senza che sia necessario definirlo in modo specifico.

L'esempio seguente illustra come impostare una proprietà associata nel codice. In questo esempio è myCheckBox un'istanza della CheckBox classe .

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 genererebbe un'eccezione, ma il valore della proprietà non interagirà con un DockPanel elemento padre e quindi non eseguirà alcuna operazione. Solo un DockPanel.Dock valore impostato su un elemento figlio combinato con la presenza di un DockPanel elemento padre 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.

Metadati delle proprietà associate

Quando si registra la proprietà, FrameworkPropertyMetadata viene impostata per specificare le caratteristiche della proprietà, ad esempio se la proprietà influisce sul rendering, la misurazione e così via. I metadati di una proprietà associata non sono in genere diversi rispetto a quelli presenti per una proprietà di dipendenza. Se si specifica un valore predefinito in un override per i metadati di una proprietà associata, tale valore diventa il valore predefinito della proprietà associata implicita nelle istanze della classe che esegue l'override. In particolare, il valore predefinito viene segnalato se un processo esegue una query per recuperare il valore di una proprietà associata tramite la funzione di accesso al metodo Get di quella proprietà, specificando un'istanza della classe in cui sono stati definiti i metadati e il valore per quella proprietà collegata non è stato impostato diversamente.

Se si vuole abilitare l'ereditarietà del valore di una proprietà, è necessario usare le proprietà associate anziché le proprietà di dipendenza non associate. Per informazioni dettagliate, vedere Ereditarietà del valore della proprietà.

Proprietà associate personalizzate

Quando creare una proprietà associata

È possibile creare una proprietà associata quando è necessario disporre di un meccanismo di impostazione delle proprietà per le classi diverse dalla classe di definizione. In questo caso, lo scenario più comune è il layout. Esempi di proprietà di layout esistenti sono DockPanel.Dock, Panel.ZIndexe Canvas.Top. Nello scenario abilitato in questo contesto, gli elementi disponibili come elementi figlio degli elementi di controllo del layout sono in grado di indicare i requisiti del layout agli elementi padre del layout singolarmente, impostando ciascuno un valore della proprietà definito dall'elemento padre come proprietà associata.

Un altro scenario per l'uso di una proprietà associata è quello in cui 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 modifica di controlli.

Come indicato in precedenza, è necessario eseguire la registrazione come proprietà associata se si vuole usare 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 public static readonly campo di tipo DependencyProperty. Questo campo viene definito usando il valore restituito del RegisterAttached metodo . Il nome del campo deve corrispondere al nome della proprietà associata, aggiunto con la 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 Get PropertyName e SetPropertyName come funzioni di accesso per la proprietà associata. Se non si riesce a eseguire questa operazione, il sistema di proprietà non è in grado di utilizzare la proprietà associata.

Nota

Se si omette la funzione di accesso get della proprietà associata, il data binding nella proprietà non funzionerà negli strumenti di progettazione, ad esempio 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 DockPanel.GetDock metodo digita il parametro come UIElement, perché la proprietà associata deve essere impostata solo nelle UIElement istanze di .

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

Funzione di accesso Set

La firma per la funzione di accesso 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 SetDock metodo lo digita come UIElement, perché la proprietà associata deve essere impostata solo nelle UIElement istanze di .

  • L'oggetto value può essere specificato come tipo più specifico nell'implementazione. Ad esempio, il SetDock metodo 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 della proprietà associata nel markup. Tale input è il valore specificato come valore di attributo XAML nel markup. Pertanto, per il tipo usato devono essere disponibili la conversione di tipo, il serializzatore del valore o il supporto per l'estensione di markup, in modo da poter creare il tipo appropriato in base al valore dell'attributo, rappresentato in pratica semplicemente da una stringa.

Nell'esempio seguente viene illustrata la registrazione della proprietà di dipendenza (usando il RegisterAttached metodo ), nonché le funzioni di accesso GetPropertyName e SetPropertyName. Nell'esempio, la proprietà associata è denominata IsBubbleSource. Pertanto, le funzioni di accesso devono essere chiamate 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à associate

WPF definisce diversi attributi .NET destinati a fornire informazioni sulle proprietà associate ai processi di reflection e agli utenti tipici di informazioni sulla reflection e sulle proprietà, ad esempio le finestre di progettazione. Dato che le proprietà associate hanno un tipo con ambito illimitato, le finestre di progettazione devono disporre di un modo per evitare di sopraffare gli utenti con un elenco globale di tutte le proprietà associate definite in una particolare implementazione della tecnologia 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à. È possibile prendere in considerazione l'applicazione di questi attributi anche per le proprietà associate personalizzate. Lo scopo e la sintassi degli attributi .NET sono descritti nelle pagine di riferimento appropriate:

Altre informazioni sulle proprietà associate

  • Per altre informazioni sulla creazione di una proprietà associata, vedere Registrare una proprietà associata.

  • Per scenari di utilizzo più avanzati delle proprietà di dipendenza e delle proprietà associate, vedere Proprietà di dipendenza personalizzate.

  • È anche possibile registrare una proprietà come proprietà associata e proprietà di dipendenza, ma continuare a esporre le implementazioni del "wrapper". In questo caso, la proprietà può essere impostata in tale elemento o in qualsiasi elemento tramite la sintassi per le proprietà associate XAML. Un esempio di proprietà con uno scenario appropriato per gli utilizzi standard e associati è FrameworkElement.FlowDirection.

Vedi anche