Panoramica dei convertitori di tipi per XAML
I convertitori di tipi forniscono logica per uno scrittore di oggetti che esegue la conversione da una stringa nel markup XAML in oggetti specifici in un grafo di oggetti. In Servizi XAML .NET il convertitore di tipi deve essere una classe che deriva da TypeConverter. Alcuni convertitori supportano anche il percorso di salvataggio XAML e possono essere usati per serializzare un oggetto in un formato stringa nel markup di serializzazione. Questo argomento descrive come e quando vengono richiamati i convertitori di tipi in XAML e fornisce consigli di implementazione per gli override del metodo di TypeConverter.
Concetti relativi alla conversione dei tipi
Le sezioni seguenti illustrano i concetti di base su come XAML usa le stringhe e sul modo in cui i writer di oggetti nei servizi XAML .NET usano convertitori di tipi per elaborare alcuni dei valori stringa rilevati in un'origine XAML.
Valori XAML e stringhe
Quando imposti un valore di attributo in un file XAML, il tipo iniziale di tale valore è una stringa in senso generale e un valore di attributo stringa in senso XML. Anche altre primitive, ad esempio Double, sono inizialmente stringhe a un processore XAML.
Nella maggior parte dei casi, un processore XAML richiede due informazioni per elaborare un valore di attributo. La prima informazione è il tipo di valore della proprietà che viene impostata. Qualsiasi stringa che definisce un valore di attributo e che viene elaborata in XAML deve essere infine convertita o risolta in un valore di quel tipo. Se il valore è una primitiva compresa dal parser XAML (ad esempio un valore numerico), viene tentata una conversione diretta della stringa. Se il valore per l'attributo fa riferimento a un'enumerazione, la stringa specificata viene verificata la corrispondenza di un nome con una costante denominata in tale enumerazione. Se il valore non è una primitiva riconosciuta dal parser o un nome costante da un'enumerazione, il tipo applicabile deve essere in grado di fornire un valore o un riferimento basato su una stringa convertita.
Nota
Le direttive del linguaggio XAML non usano convertitori di tipi.
Convertitori di tipi ed estensioni di markup
Gli utilizzi delle estensioni di markup devono essere gestiti da un processore XAML prima che verifichi il tipo di proprietà e prenda in considerazione altri aspetti. Ad esempio, se una proprietà impostata come attributo ha normalmente una conversione di tipo, ma in un caso specifico viene impostata tramite un utilizzo dell'estensione di markup, allora viene prima elaborato il comportamento dell'estensione di markup. Una situazione comune in cui è necessaria un'estensione di markup è creare un riferimento a un oggetto già esistente. Per questo scenario, un convertitore di tipi stateless può generare solo una nuova istanza, che potrebbe non essere desiderabile. Per ulteriori informazioni sulle estensioni di markup, vedere Markup Extensions for XAML Overview.
Convertitori di tipi nativi
Nelle implementazioni di Windows Presentation Foundation (WPF) e dei servizi XAML di .NET, esistono alcuni tipi CLR che dispongono di una gestione nativa per la conversione dei tipi. Tuttavia, questi tipi CLR non sono generalmente considerati delle primitive. Un esempio di tale tipo è DateTime. Un motivo è il funzionamento dell'architettura di .NET Framework: il tipo DateTime è definito in mscorlib, la libreria più semplice in .NET. Non è consentito attribuire a DateTime un attributo proveniente da un altro assembly che introduce una dipendenza (TypeConverterAttribute proviene da System). Di conseguenza, il normale meccanismo di individuazione del convertitore di tipi per attribuzione non può essere supportato. Al contrario, il parser XAML include un elenco di tipi che richiedono l'elaborazione nativa ed elabora questi tipi in modo simile al modo in cui vengono elaborate le primitive vere. Nel caso di DateTime, questa elaborazione comporta una chiamata a Parse.
Implementazione di un convertitore di tipi
Le sezioni seguenti illustrano l'API della classe TypeConverter.
TypeConverter
In Servizi XAML .NET tutti i convertitori di tipi usati per scopi XAML sono classi che derivano dalla classe base TypeConverter. La classe TypeConverter esisteva nelle versioni del .NET Framework prima che esistesse XAML; uno degli scenari originali di TypeConverter consisteva nel fornire la conversione di stringhe per gli editor di proprietà nei progettisti visivi.
Per XAML, il ruolo di TypeConverter viene espanso. Ai fini di XAML, TypeConverter è la classe di base per fornire supporto per determinate conversioni da stringa a oggetto e da oggetto a stringa. From-string permette di interpretare il valore di un attributo stringa da XAML. Potrebbe consentire di elaborare nuovamente un valore di runtime di una particolare proprietà dell'oggetto come attributo in XAML per la serializzazione.
TypeConverter definisce quattro membri rilevanti per la conversione in stringa e da stringa per scopi di elaborazione XAML.
Di questi membri, il metodo più importante è ConvertFrom, che converte la stringa di input nel tipo di oggetto richiesto. Il metodo ConvertFrom può essere implementato per convertire una gamma più ampia di tipi nel tipo di destinazione previsto del convertitore. Pertanto, può servire a scopi che si estendono oltre XAML, ad esempio il supporto delle conversioni in fase di esecuzione. Tuttavia, per l'uso xaml, è importante solo il percorso del codice in grado di elaborare un input String.
Il secondo metodo più importante è ConvertTo. Se un'applicazione viene convertita in una rappresentazione di markup (ad esempio, se viene salvata in XAML come file), ConvertTo è coinvolto nello scenario più ampio di un writer di testo XAML per produrre una rappresentazione di markup. In questo caso, il percorso di codice importante per XAML è quando il chiamante passa un valore di destinationType
a String.
CanConvertTo e CanConvertFrom sono metodi di supporto usati quando un servizio esegue una query sulle funzionalità dell'implementazione TypeConverter. È necessario implementare questi metodi per restituire true
nei casi specifici di tipo supportati dai metodi di conversione equivalenti del vostro convertitore. Per scopi XAML, questo significa in genere il tipo String.
Informazioni culturali e convertitori di tipi per XAML
Ogni implementazione TypeConverter può interpretare in modo univoco ciò che è una stringa valida per una conversione e può anche usare o ignorare la descrizione del tipo passata come parametri. Una considerazione importante per la cultura e la conversione dei tipi XAML è la seguente: anche se l'uso di stringhe localizzabili come valori di attributo è supportato da XAML, non è possibile usare queste stringhe localizzabili come input del convertitore di tipi con requisiti culturali specifici. Questa limitazione è dovuta al fatto che i convertitori di tipi per i valori degli attributi XAML implicano un comportamento di elaborazione XAML con linguaggio predefinito che utilizza la cultura standard en-US
. Per altre informazioni sui motivi di progettazione per questa restrizione, vedere la specifica del linguaggio XAML ([MS-XAML]) o Cenni preliminari sulla globalizzazione e la localizzazione WPF.
Come esempio in cui la cultura può essere un problema, alcune culture usano una virgola anziché un punto come delimitatore decimale per i numeri nella loro forma testuale. Questo uso si scontra con il comportamento di molti convertitori di tipi esistenti, ovvero l'uso di una virgola come delimitatore. Il passaggio di un'impostazione della cultura tramite xml:lang
nel codice XAML circostante non risolve il problema.
Implementazione di ConvertFrom
Per essere utilizzabile come implementazione di TypeConverter che supporta XAML, il metodo ConvertFrom per tale convertitore deve accettare una stringa come parametro value
. Se la stringa è in un formato valido e può essere convertita dall'implementazione TypeConverter, l'oggetto restituito deve essere in grado di essere convertito nel tipo previsto dalla proprietà. In caso contrario, l'implementazione ConvertFrom deve restituire null
.
Ogni implementazione TypeConverter può interpretare in modo univoco ciò che costituisce una stringa considerata valida ai fini di una conversione e può anche usare o ignorare la descrizione del tipo o i contesti culturali forniti come parametri. Tuttavia, l'elaborazione XAML di WPF potrebbe non passare valori al contesto di descrizione del tipo in tutti i casi e potrebbe anche non trasmettere correttamente le impostazioni culturali basate su xml:lang
.
Nota
Non usare le parentesi graffe ({}), in particolare la parentesi graffa di apertura ({), come elemento del formato stringa. Questi caratteri sono riservati come ingresso e uscita per una sequenza di estensioni di marcatura.
È opportuno generare un'eccezione quando il convertitore di tipi deve avere accesso a un servizio XAML dallo scrittore di oggetti dei servizi .NET XAML, ma la chiamata GetService al contesto non restituisce tale servizio.
Implementazione di ConvertTo
ConvertTo viene potenzialmente usato per il supporto della serializzazione. Il supporto della serializzazione tramite ConvertTo per il tipo personalizzato e il relativo convertitore di tipi non è un requisito assoluto. Tuttavia, se si implementa un controllo o si usa la serializzazione di come parte delle funzionalità o della progettazione della classe, è necessario implementare ConvertTo.
Per essere utilizzabile come implementazione di TypeConverter che supporta XAML, il metodo ConvertTo per tale convertitore deve accettare un'istanza del tipo (o un valore) supportato come parametro value
. Quando il parametro destinationType
è di tipo String, l'oggetto restituito deve essere in grado di essere convertito in String. La stringa restituita deve rappresentare un valore serializzato di value
. Idealmente, il formato di serializzazione scelto dovrebbe essere in grado di generare lo stesso valore di se tale stringa fosse passata all'implementazione ConvertFrom dello stesso convertitore, senza perdita significativa di informazioni.
Se il valore non può essere serializzato o il convertitore non supporta la serializzazione, l'implementazione ConvertTo deve restituire null
e può generare un'eccezione. Tuttavia, se si generano eccezioni, è consigliabile segnalare l'impossibilità di usare tale conversione come parte dell'implementazione CanConvertTo in modo che la procedura consigliata di controllare con CanConvertTo prima di evitare eccezioni sia supportata.
Se il parametro destinationType
non è di tipo String, è possibile scegliere la gestione del convertitore personalizzata. In genere, si ripristina la gestione dell'implementazione di base, che nella ConvertTo di base genera un'eccezione specifica.
È opportuno generare un'eccezione quando il convertitore di tipi deve accedere a un servizio XAML dal writer di oggetti di .NET XAML Services, ma la chiamata GetService effettuata sul contesto non restituisce tale servizio.
Implementazione di CanConvertFrom
L'implementazione CanConvertFrom deve restituire true
per sourceType
di tipo String e in caso contrario, rinviare all'implementazione di base. Non lanciare eccezioni da CanConvertFrom.
Implementazione di CanConvertTo
L'implementazione CanConvertTo dovrebbe restituire true
per destinationType
di tipo Stringe altrimenti fare riferimento all'implementazione di base. Non generare eccezioni da CanConvertTo.
Applicazione dell'attributo TypeConverterAttribute
Affinché il convertitore di tipi personalizzato venga usato come convertitore di tipi per una classe personalizzata dai servizi XAML .NET, devi applicare il TypeConverterAttribute alla definizione della classe. Il ConverterTypeName che specifichi tramite l'attributo deve essere il nome del tipo del tuo convertitore di tipi personalizzato. Se si applica questo attributo, quando un processore XAML gestisce i valori in cui il tipo di proprietà usa il tipo di classe personalizzato, può immettere stringhe e restituire istanze dell'oggetto.
È anche possibile fornire un convertitore di tipi su base individuale per ciascuna proprietà. Anziché applicare un TypeConverterAttribute alla definizione della classe, applicarlo a una definizione di proprietà (la definizione principale, non le implementazioni get
/set
al suo interno). Il tipo della proprietà deve corrispondere al tipo elaborato dal convertitore di tipi personalizzato. Con questo attributo applicato, quando un processore XAML gestisce i valori di tale proprietà, può elaborare stringhe di input e restituire istanze dell'oggetto. La tecnica del convertitore di tipi per proprietà è utile se si sceglie di usare un tipo di proprietà da Microsoft .NET Framework o da un'altra libreria in cui non è possibile controllare la definizione della classe e non è possibile applicare un TypeConverterAttribute in questa posizione.
Per fornire un comportamento di conversione dei tipi per un membro collegato personalizzato, applicare TypeConverterAttribute al metodo di accesso Get
del modello di implementazione per il membro collegato.
Accesso al contesto del fornitore di servizi da un'implementazione dell'estensione di markup
I servizi disponibili sono gli stessi per qualsiasi convertitore di valori. La differenza consiste nel modo in cui ogni convertitore di valori riceve il contesto del servizio. L'accesso ai servizi e i servizi disponibili sono documentati nell'argomento Convertitori di tipi ed estensioni di markup per XAML.
Convertitori di tipi nel flusso del nodo XAML
Se si usa un flusso di nodi XAML, l'azione o il risultato finale di un convertitore di tipi non viene ancora eseguito. In un percorso di caricamento, la stringa di attributo che alla fine deve essere convertita di tipo per il caricamento rimane come valore di testo all'interno di un membro iniziale e di un membro finale. Il convertitore di tipi necessario per questa operazione può essere determinato usando la proprietà XamlMember.TypeConverter. Tuttavia, ottenere un valore valido da XamlMember.TypeConverter si basa sulla presenza di un contesto dello schema XAML, che può accedere a tali informazioni tramite il membro sottostante o il tipo del valore dell'oggetto usato dal membro. Per richiamare il comportamento di conversione del tipo è necessario anche il contesto dello schema XAML perché richiede il mapping dei tipi e la creazione di un'istanza del convertitore.
Vedere anche
.NET Desktop feedback