Metadati della proprietà di dipendenza
Il sistema di proprietà di Windows Presentation Foundation (WPF) include un sistema di segnalazione dei metadati che va al di là di ciò che è possibile segnalare riguardo una proprietà tramite la reflection o le caratteristiche common language runtime (CLR) generali. I metadati di una proprietà di dipendenza possono anche essere assegnati in modo univoco dalla classe che definisce una proprietà di dipendenza, possono essere modificati quando la proprietà di dipendenza viene aggiunta a una classe diversa ed è possibile eseguirne specificatamente l'override tramite tutte le classi derivate che ereditano la proprietà di dipendenza dalla classe base in fase di definizione.
Nel presente argomento sono contenute le seguenti sezioni.
- Prerequisiti
- Utilizzo dei metadati della proprietà di dipendenza
- API dei metadati
- Esecuzione dell'override dei metadati e derivazione di una classe
- Scenari per la modifica dei metadati esistenti
- Argomenti correlati
Prerequisiti
In questo argomento si presuppone la conoscenza delle proprietà di dipendenza dal punto di vista di un consumer delle proprietà di dipendenza esistenti nelle classi Windows Presentation Foundation (WPF), nonché la lettura di Cenni preliminari sulle proprietà di dipendenza. Per seguire gli esempi di questo argomento, è necessaria inoltre la comprensione di XAML oltre che la conoscenza della modalità di scrittura delle applicazioni WPF.
Utilizzo dei metadati della proprietà di dipendenza
I metadati della proprietà di dipendenza sono un oggetto sul quale è possibile eseguire query per esaminare le caratteristiche di una proprietà di dipendenza. Anche il sistema di proprietà accede frequentemente ai metadati durante l'elaborazione di una data proprietà di dipendenza. L'oggetto metadati di una proprietà di dipendenza può contenere i seguenti tipi di informazioni:
Valore predefinito della proprietà di dipendenza, se non è possibile determinare altri valori per la proprietà di dipendenza in base al valore locale, stile, ereditarietà e così via. Per una discussione accurata sul ruolo dei valori predefiniti nella precedenza utilizzata dal sistema di proprietà durante l'assegnazione dei valori per le proprietà di dipendenza, vedere Precedenza del valore della proprietà di dipendenza.
I riferimenti a implementazioni di callback che influiscono sui comportamenti di coercizione o di notifica di modifica in base al tipo di proprietario. Notare che questi callback vengono spesso definiti con un livello di accesso non pubblico, pertanto in genere non è possibile ottenere i riferimenti effettivi dai metadati, a meno che i riferimenti non rientrino nell'ambito di accesso consentito. Per ulteriori informazioni sui callback delle proprietà di dipendenza, vedere Callback e convalida delle proprietà di dipendenza.
Se la proprietà di dipendenza in questione viene considerata come una proprietà a livello di framework WPF, è possibile che i metadati contengano caratteristiche della proprietà di dipendenza a livello di framework WPF che consentono di segnalare le informazioni e lo stato relativo a servizi quali il motore di layout a livello di framework WPF e la logica dell'ereditarietà della proprietà. Per ulteriori informazioni su questo aspetto dei metadati della proprietà di dipendenza, vedere Metadati delle proprietà del framework.
API dei metadati
Il tipo che segnala la maggior parte delle informazioni sui metadati utilizzate dal sistema di proprietà è la classe PropertyMetadata. Le istanze dei metadati possono essere specificate facoltativamente quando le proprietà di dipendenza vengono registrate con il sistema di proprietà e una seconda volta per i tipi che si aggiungono come proprietari o che eseguono l'override dei metadati ereditati dalla definizione della proprietà di dipendenza della classe base. Nei casi in cui durante una registrazione della proprietà non vengono specificati i metadati, viene creato un oggetto PropertyMetadata predefinito con i valori predefiniti per quella classe. I metadati registrati vengono restituiti come oggetto PropertyMetadata al momento della chiamata ai diversi overload di GetMetadata che ottengono i metadati da una proprietà di dipendenza nell'istanza di un oggetto DependencyObject.
La classe PropertyMetadata è derivata per fornire metadati specifici per le divisioni architetturali quali le classi a livello di framework WPF. UIPropertyMetadata aggiunge segnalazioni di animazione e FrameworkPropertyMetadata fornisce le proprietà a livello di framework WPF indicate nella sezione precedente. La registrazione delle proprietà di dipendenza può essere eseguita con queste classi derivate PropertyMetadata. Quando i metadati vengono esaminati, è possibile eseguire il cast del tipo PropertyMetadata di base nelle classi derivate, in modo da poter esaminare le proprietà più specifiche.
Nota |
---|
Talvolta, le caratteristiche della proprietà che possono essere specificate nell'oggetto FrameworkPropertyMetadata vengono indicate con il nome di "flag" all'interno di questa documentazione.Quando si creano nuove istanze dei metadati da utilizzare per le registrazioni delle proprietà di dipendenza o per gli override dei metadati, è necessario specificare questi valori utilizzando l'enumerazione flag per flag FrameworkPropertyMetadataOptions e quindi fornire valori possibilmente concatenati dell'enumerazione al costruttore FrameworkPropertyMetadata.Tuttavia, una volta create, queste caratteristiche dell'opzione vengono esposte all'interno di un oggetto FrameworkPropertyMetadata come serie di proprietà booleane, anziché come valore di enumerazione di creazione.Le proprietà booleane consentono di verificare ogni istruzione condizionale anziché richiedere l'applicazione di una maschera a un valore di enumerazione basato su flag per ottenere le informazioni necessarie.Il costruttore utilizza il FrameworkPropertyMetadataOptions concatenato per mantenere la lunghezza della firma del costruttore entro limiti ragionevoli, mentre il metadato effettivamente costruito espone le proprietà discrete per rendere più intuitiva l'esecuzioni di query sul metadato. |
Esecuzione dell'override dei metadati e derivazione di una classe
Il sistema di proprietà di WPF dispone di funzionalità definite che consentono di modificare alcune caratteristiche della proprietà di dipendenza senza richiederne una implementazione nuova e completa. Tale risultato si ottiene creando un'istanza diversa dei metadati della proprietà per la proprietà di dipendenza presente in un tipo particolare. Notare che le proprietà di dipendenza non sono per la maggior parte proprietà virtuali, pertanto, a rigor di termini, "una nuova implementazione" di queste proprietà nelle classi ereditate potrebbe essere realizzata solo nascondendo il membro esistente.
Se lo scenario che si tenta di abilitare per una proprietà di dipendenza in un tipo non può essere realizzato modificando le caratteristiche delle proprietà di dipendenza esistenti, potrebbe essere necessario creare una classe derivata e successivamente dichiarare una proprietà di dipendenza personalizzata nella classe derivata. Il comportamento di una proprietà di dipendenza personalizzata è identico a quello delle proprietà di dipendenza definite dalle APIs WPF. Per ulteriori informazioni sulle proprietà di dipendenza personalizzate, vedere Proprietà Dependency personalizzate.
Una caratteristica rilevante di una proprietà di dipendenza di cui non è possibile eseguire l'override è il tipo valore. Se si eredita una proprietà di dipendenza che si comporta nel modo richiesto, ma si richiede un tipo diverso per questa proprietà, sarà necessario implementare una proprietà di dipendenza personalizzata e forse collegare le proprietà tramite la conversione dei tipi oppure un'altra implementazione nella classe personalizzata. Inoltre, non è possibile sostituire un oggetto ValidateValueCallback esistente, poiché questo callback è presente nel campo di registrazione stesso e non all'interno dei metadati.
Scenari per la modifica dei metadati esistenti
Se si utilizzano i metadati di una proprietà di dipendenza esistente, uno scenario comune per modificare i metadati della proprietà di dipendenza consiste nella modifica del valore predefinito. La modifica o l'aggiunta di callback del sistema di proprietà rappresenta uno scenario più avanzato. Questa operazione può essere necessaria quando l'implementazione di una classe derivata dispone di molte interrelazioni tra le proprietà di dipendenza. Una delle condizioni per poter disporre di un modello di programmazione che supporti l'utilizzo del codice e l'utilizzo dichiarativo consiste nella possibilità di impostare le proprietà in qualsiasi ordine. In tal modo, per le proprietà dipendenti deve essere utilizzata l'impostazione JIT senza contesto e senza la possibilità di basarsi sulla conoscenza di un ordine di impostazione, come potrebbe accadere in un costruttore. Per ulteriori informazioni su questo aspetto del sistema di proprietà, vedere Callback e convalida delle proprietà di dipendenza. Notare che i callback di convalida non fanno parte dei metadati, bensì dell'identificatore della proprietà di dipendenza. Pertanto, i callback di convalida non possono essere modificati mediante l'override dei metadati.
In alcuni casi, è possibile che si decida di modificare le opzioni dei metadati della proprietà a livello di framework WPF nelle proprietà di dipendenza esistenti. Tali opzioni consentono di comunicare alcune condizioni note relativi alle proprietà a livello di framework WPF ad altri processi a livello di framework WPF, ad esempio il sistema di layout. L'impostazione delle opzioni in genere viene eseguita solo quando si registra una nuova proprietà di dipendenza, tuttavia è anche possibile modificare i metadati della proprietà a livello di framework WPF come parte di una chiamata a un oggetto OverrideMetadata o AddOwner. Per conoscere i valori specifici da utilizzare e per ulteriori informazioni, vedere Metadati delle proprietà del framework. Per ulteriori informazioni relative alla modalità di impostazione di queste opzioni per una proprietà di dipendenza appena registrata, vedere Proprietà Dependency personalizzate.
Esecuzione dell'override dei metadati
Lo scopo dell'esecuzione dell'override dei metadati consiste principalmente nella possibilità di modificare i diversi comportamenti derivati dai metadati applicati alla proprietà di dipendenza presente nel tipo. Le ragioni di questa operazione vengono spiegate più dettagliatamente nella sezione Metadati. Per ulteriori informazioni e gli esempi di codice, vedere Procedura: eseguire l'override dei metadati per una proprietà di dipendenza.
I metadati della proprietà possono essere forniti per una proprietà di dipendenza durante la chiamata di registrazione (Register). Tuttavia, in molti casi è possibile fornire metadati specifici del tipo per la classe, nel momento in cui questa eredita tale proprietà di dipendenza. Tale operazione può essere eseguita chiamando il metodo OverrideMetadata. Per un esempio relativo alle APIs WPF, la classe FrameworkElement è il primo tipo a registrare la proprietà di dipendenza Focusable. Tuttavia, la classe Control esegue l'override dei metadati affinché la proprietà di dipendenza fornisca il proprio valore predefinito iniziale, modificandolo da false a true e in caso contrario riutilizza l'implementazione di Focusable originale.
Quando si esegue l'override dei metadati, le diverse caratteristiche dei metadati vengono unite oppure sostituite.
L'oggetto PropertyChangedCallback viene unito. Se si aggiunge un nuovo oggetto PropertyChangedCallback, quel callback viene archiviato nei metadati. Se non si specifica un oggetto PropertyChangedCallback nell'override, il valore dell'oggetto PropertyChangedCallback viene promosso come riferimento dal predecessore più vicino che lo aveva specificato nei metadati.
Il comportamento effettivo del sistema di proprietà per l'oggetto PropertyChangedCallback prevede che le implementazioni di tutti i proprietari di metadati nella gerarchia siano mantenute e aggiunte a una tabella, con un ordine di esecuzione da parte del sistema di proprietà che indichi che i callback della classe con il maggior numero di derivazioni siano richiamati per primi.
L'oggetto DefaultValue viene sostituito. Se non si specifica un oggetto DefaultValue nell'override, il valore dell'oggetto DefaultValue proviene dal predecessore più vicino che lo aveva specificato nei metadati.
Le implementazioni di CoerceValueCallback vengono sostituite. Se si aggiunge un nuovo oggetto CoerceValueCallback, quel callback viene archiviato nei metadati. Se non si specifica un oggetto CoerceValueCallback nell'override, il valore dell'oggetto CoerceValueCallback viene promosso come riferimento dal predecessore più vicino che lo aveva specificato nei metadati.
Il comportamento del sistema di proprietà prevede che venga richiamato solo l'oggetto CoerceValueCallback dei metadati diretti. Non viene mantenuto alcun riferimento ad altre implementazioni di CoerceValueCallback all'interno della gerarchia.
Questo comportamento viene implementato mediante l'oggetto Merge ed è possibile eseguirne l'override nelle classi di metadati derivate.
Esecuzione dell'override dei metadati delle proprietà associate
In WPF, le proprietà associate vengono implementate come proprietà di dipendenza. In altri termini, dispongono anche di metadati della proprietà di cui le singole classi possono eseguirne l'override. Le considerazioni sull'ambito relative a una proprietà associata in WPF prevedono in genere la possibilità di impostare una proprietà associata per tutti gli oggetti DependencyObject. Pertanto, qualsiasi classe derivata DependencyObject può eseguire l'override dei metadati per una proprietà associata, poiché potrebbe essere impostata in un'istanza della classe. È possibile eseguire l'override dei valori predefiniti, dei callback o delle proprietà di segnalazione delle caratteristiche a livello di framework WPF. Se la proprietà associata viene impostata su un'istanza della classe, vengono applicate le caratteristiche dei metadati della proprietà di override. È possibile, ad esempio, eseguire l'override del valore predefinito, in modo che il valore di override venga segnalato come valore della proprietà associata nelle istanze della classe, tutte le volte che la proprietà non viene impostata diversamente.
Nota |
---|
La proprietà Inherits non è rilevante per le proprietà associate. |
Aggiunta di un classe come proprietario di una proprietà di dipendenza esistente
Una classe può aggiungersi come proprietario di una proprietà di dipendenza già registrata, utilizzando il metodo AddOwner. In questo modo, la classe può utilizzare una proprietà di dipendenza registrata originariamente per un tipo diverso. In genere, la classe aggiunta non è una classe derivata del tipo che ha registrato per primo quella proprietà di dipendenza come proprietario. In realtà, in questo modo la classe e le relative classi derivate possono "ereditare" un'implementazione della proprietà di dipendenza senza che la classe proprietario originale e quella aggiunta si trovino nella stessa gerarchia di classi. Inoltre, la classe aggiunta (e tutte le classi derivate) possono quindi fornire metadati specifici sul tipo per la proprietà di dipendenza originale.
Oltre ad aggiungersi come proprietario tramite i metodi di utilità del sistema di proprietà, la classe aggiunta deve dichiarare ulteriori membri pubblici al proprio interno al fine di far partecipare completamente la proprietà di dipendenza nel sistema di proprietà con l'esposizione al codice e al markup. Una classe che aggiunge una proprietà di dipendenza esistente ha le stesse responsabilità, per quanto riguarda l'esposizione del modello a oggetti per quella proprietà di dipendenza, di una classe che definisce una nuova proprietà di dipendenza personalizzata. Il primo di questi membri da esporre è un campo dell'identificatore della proprietà di dipendenza. Questo campo deve essere un campo public static readonly di tipo DependencyProperty, al quale viene assegnato il valore restituito della chiamata a AddOwner. Il secondo membro da definire è la proprietà "wrapper" common language runtime (CLR). Il wrapper rende più semplice la modifica della proprietà di dipendenza nel codice (si evita di chiamare ogni volta l'oggetto SetValue ed è possibile eseguire tale chiamata una sola volta all'interno del wrapper stesso). Il wrapper viene implementato con la stessa procedura utilizzata per i wrapper implementati nella registrazione di una proprietà di dipendenza personalizzata. Per ulteriori informazioni sull'implementazione di una proprietà di dipendenza, vedere Proprietà Dependency personalizzate e Procedura: aggiungere un tipo di proprietario per una proprietà di dipendenza.
AddOwner e proprietà associate
È possibile chiamare l'oggetto AddOwner per una proprietà di dipendenza definita come proprietà associata dalla classe proprietario. In genere, questa operazione viene eseguita per esporre la proprietà precedentemente associata come proprietà di dipendenza non associata. Successivamente, il valore restituito dell'oggetto AddOwner verrà esposto come campo public static readonly da utilizzare come identificatore della proprietà di dipendenza e verranno definite proprietà "wrapper" appropriate, in modo che la proprietà venga visualizzata nella tabella dei membri e supporti l'utilizzo di una proprietà non associata all'interno della classe.