Metadati delle proprietà di dipendenza

Il sistema di proprietà Windows Presentation Foundation (WPF) include un sistema di creazione di report dei metadati che va oltre ciò che può essere segnalato su una proprietà tramite reflection o caratteristiche CLR (Common Language Runtime) 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 di base in fase di definizione.

Prerequisiti

In questo argomento si presuppone che le proprietà di dipendenza siano comprensibili dal punto di vista di un consumer di proprietà di dipendenza esistenti nelle classi WPF e che siano state lette le informazioni generali sulle proprietà di dipendenza. Per seguire gli esempi illustrati in questo argomento, è anche necessario conoscere XAML e saper scrivere applicazioni WPF.

Come usare i metadati delle 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 qualsiasi proprietà di dipendenza. L'oggetto metadati di una proprietà di dipendenza può contenere i seguenti tipi di informazioni:

  • Valore predefinito per la proprietà di dipendenza, se non è possibile determinare altri valori per la proprietà di dipendenza in base al valore locale, allo stile, all'ereditarietà e così via. Per una descrizione approfondita del modo in cui i valori predefiniti partecipano alla precedenza usata dal sistema di proprietà quando si assegnano 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 altre informazioni sui callback per le 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, i metadati potrebbero contenere caratteristiche della proprietà di dipendenza a livello di framework WPF, che segnalano informazioni e stato per servizi come la logica di ereditarietà delle proprietà e il motore di layout a livello di framework WPF. Per altre informazioni su questo aspetto dei metadati delle proprietà di dipendenza, vedere Metadati delle proprietà del framework.

API dei metadati

Il tipo che segnala la maggior parte delle informazioni sui metadati usate dal sistema di proprietà è la PropertyMetadata classe . Le istanze dei metadati possono essere specificate facoltativamente quando le proprietà di dipendenza vengono registrate nel 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 di base. Nei casi in cui la registrazione di una proprietà non specifica i metadati, viene creato un valore predefinito PropertyMetadata con valori predefiniti per tale classe. I metadati registrati vengono restituiti come PropertyMetadata quando si chiamano i vari GetMetadata overload che ottengono metadati da una proprietà di dipendenza in un'istanza DependencyObject di .

La PropertyMetadata classe viene quindi derivata da per fornire metadati più specifici per le divisioni architetturali, ad esempio le classi a livello di framework WPF. UIPropertyMetadata aggiunge report di animazione e FrameworkPropertyMetadata fornisce le proprietà a livello di framework WPF indicate nella sezione precedente. Quando le proprietà di dipendenza vengono registrate, possono essere registrate con queste PropertyMetadata classi derivate. Quando vengono esaminati i metadati, è possibile eseguire il cast del tipo di base PropertyMetadata alle classi derivate in modo da poter esaminare le proprietà più specifiche.

Nota

Le caratteristiche delle proprietà che possono essere specificate in FrameworkPropertyMetadata sono talvolta indicate in questa documentazione come "flag". Quando si creano nuove istanze di metadati da usare nelle registrazioni delle proprietà di dipendenza o nelle sostituzioni di metadati, specificare questi valori usando l'enumerazione FrameworkPropertyMetadataOptions flag per flag e quindi specificare valori eventualmente concatenati dell'enumerazione al FrameworkPropertyMetadata costruttore. Tuttavia, una volta costruite, queste caratteristiche di opzione vengono esposte all'interno di come FrameworkPropertyMetadata una serie di proprietà booleane anziché come valore di enumerazione di costruzione. 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 usa la concatenata FrameworkPropertyMetadataOptions per mantenere ragionevole la lunghezza della firma del costruttore, mentre i metadati costruiti effettivi espongono le proprietà discrete per rendere più intuitiva l'esecuzione di query sui metadati.

Esecuzione dell'override dei metadati e derivazione di una classe

Il sistema di proprietà WPF ha stabilito funzionalità per modificare alcune caratteristiche delle proprietà di dipendenza senza che siano completamente implementate. Questo 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. Una proprietà di dipendenza personalizzata si comporta in modo identico alle proprietà di dipendenza definite dalle API WPF. Per altri dettagli sulle proprietà di dipendenza personalizzate, vedere Proprietà di dipendenza personalizzate.

Una caratteristica rilevante di una proprietà di dipendenza di cui non è possibile eseguire l'override è il tipo di valore. Se si eredita una proprietà di dipendenza che si comporta nel modo richiesto, ma è richiesto 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 esistente ValidateValueCallbackperché questo callback esiste nel campo di registrazione stesso e non all'interno dei relativi metadati.

Scenari per la modifica dei metadati esistenti

Se si usano 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 ha 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. Le proprietà dipendenti devono quindi essere impostate JIT senza contesto e senza la possibilità di basarsi sulla conoscenza di un ordine di impostazione, come potrebbe accadere in un costruttore. Per altre 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, ma dell'identificatore della proprietà di dipendenza. I callback di convalida non possono quindi essere modificati mediante l'override dei metadati.

In alcuni casi, è possibile che si decida di modificare le opzioni dei metadati delle proprietà a livello di framework WPF nelle proprietà di dipendenza esistenti. Queste opzioni consentono di comunicare alcune condizioni note relative 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 viene in genere eseguita solo quando si registra una nuova proprietà di dipendenza, ma è anche possibile modificare i metadati delle proprietà a livello di framework WPF come parte di una OverrideMetadata chiamata o AddOwner . Per conoscere i valori specifici da usare e per altre informazioni, vedere Metadati delle proprietà del framework. Per altre informazioni relative alla modalità di impostazione di queste opzioni per una proprietà di dipendenza appena registrata, vedere Proprietà di dipendenza personalizzate.

Override dei metadati

Lo scopo dell'override dei metadati è principalmente la possibilità di modificare i diversi comportamenti derivati dai metadati applicati alla proprietà di dipendenza esistente per il tipo. Le ragioni di questa operazione vengono spiegate più dettagliatamente nella sezione Metadati. Per altre informazioni e alcuni esempi di codice, vedere Eseguire l'override dei metadati per una proprietà di dipendenza.

I metadati delle 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, quando questa eredita tale proprietà di dipendenza. A tale scopo, chiamare il OverrideMetadata metodo . Per un esempio delle API WPF, la FrameworkElement classe è il tipo che registra prima la Focusable proprietà di dipendenza. Tuttavia, la classe esegue l'override Control dei metadati per la proprietà di dipendenza per fornire il proprio valore predefinito iniziale, modificandolo da false a truee altrimenti riesempe l'implementazione originale Focusable .

Quando si esegue l'override dei metadati, le diverse caratteristiche dei metadati vengono unite oppure sostituite.

  • PropertyChangedCallback viene unito. Se si aggiunge un nuovo PropertyChangedCallback, il callback viene archiviato nei metadati. Se non si specifica un oggetto PropertyChangedCallback nell'override, il valore di PropertyChangedCallback viene promosso come riferimento dal predecessore più vicino che lo ha specificato nei metadati.

  • Il comportamento effettivo del sistema di proprietà per PropertyChangedCallback è che le implementazioni per tutti i proprietari di metadati nella gerarchia vengono mantenute e aggiunte a una tabella, con ordine di esecuzione da parte del sistema di proprietà in quanto i callback della classe più derivata vengono richiamati per primi.

  • DefaultValue viene sostituito. Se non si specifica un oggetto DefaultValue nell'override, il valore di DefaultValue proviene dal predecessore più vicino che lo ha specificato nei metadati.

  • CoerceValueCallback le implementazioni vengono sostituite. Se si aggiunge un nuovo CoerceValueCallback, il callback viene archiviato nei metadati. Se non si specifica un oggetto CoerceValueCallback nell'override, il valore di CoerceValueCallback viene promosso come riferimento dal predecessore più vicino che lo ha specificato nei metadati.

  • Il comportamento del sistema di proprietà è che viene richiamato solo nei CoerceValueCallback metadati immediati. Non vengono mantenuti riferimenti ad altre CoerceValueCallback implementazioni della gerarchia.

Questo comportamento viene implementato da Mergee può essere sottoposto a override nelle classi di metadati derivate.

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 eseguire l'override. Le considerazioni di ambito per una proprietà associata in WPF sono in genere che qualsiasi DependencyObject proprietà associata può essere impostata su di esse. Pertanto, qualsiasi DependencyObject classe derivata può eseguire l'override dei metadati per qualsiasi proprietà associata, in quanto 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 Inherits proprietà 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 tramite il AddOwner metodo . In questo modo, la classe può usare 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 public static readonly campo di tipo DependencyProperty, assegnato al valore restituito della AddOwner chiamata. Il secondo membro da definire è la proprietà "wrapper" di Common Language Runtime (CLR). Il wrapper rende molto più pratico modificare la proprietà di dipendenza nel codice (evitare chiamate a SetValue ogni volta e può effettuare tale chiamata una sola volta nel wrapper stesso). Il wrapper viene implementato con la stessa procedura valida per i wrapper implementati nella registrazione di una proprietà di dipendenza personalizzata. Per altre informazioni sull'implementazione di una proprietà di dipendenza, vedere Proprietà di dipendenza personalizzate e Aggiungere un tipo di proprietario per una proprietà di dipendenza.

AddOwner e proprietà associate

È possibile chiamare 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. Il valore restituito verrà quindi esposto AddOwner come public static readonly campo da usare come identificatore della proprietà di dipendenza e definirà le proprietà "wrapper" appropriate in modo che la proprietà venga visualizzata nella tabella dei membri e supporti un utilizzo di proprietà non associato nella classe.

Vedi anche