Panoramica dei convertitori di tipi per XAML

I convertitori di tipi forniscono la logica per un writer di oggetti che esegue una conversione da una stringa nel markup XAML in particolari oggetti in un oggetto grafico. Nei 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 vengono forniti consigli di implementazione per gli override del metodo di TypeConverter.

Concetti relativi alla conversione di 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 stringa

Quando si imposta un valore dell'attributo in un file XAML, il tipo iniziale del valore è una stringa in senso generale e un valore dell'attributo di stringa in XML. Anche altre primitive, ad esempio Double , sono inizialmente stringhe per un processore XAML.

Nella maggior parte dei casi, un processore XAML deve disporre di due informazioni per elaborare un valore di attributo. La prima informazione è il tipo di valore della proprietà che si imposta. Qualsiasi stringa che definisce un valore di attributo e che viene elaborata in XAML deve essere convertita o risolta in un valore di quel tipo. Se il valore è una primitiva riconosciuta dal parser XAML (ad esempio un valore numerico), viene tentata una conversione diretta della stringa. Se il valore dell'attributo fa riferimento a un'enumerazione, nella stringa specificata viene verificata la corrispondenza del 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 di estensioni di markup devono essere gestiti da un processore XAML prima che questo verifichi il tipo di proprietà e altre considerazioni. Ad esempio, se una proprietà impostata come attributo viene associata normalmente a una conversione di tipi, ma in un caso particolare viene impostata mediante un utilizzo dell'estensione di markup, viene innanzitutto elaborato il comportamento dell'estensione di markup. Una situazione comune che richiede un'estensione di markup è la creazione di un riferimento a un oggetto già esistente. Per questo scenario, un convertitore di tipi senza stato può solo generare una nuova istanza, che non necessariamente è appropriata. 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 .NET esistono alcuni tipi CLR con gestione della conversione dei tipi nativa. Tuttavia, questi tipi CLR non vengono considerati convenzionalmente come primitive. Un esempio dei tipi in questione è DateTime. Un motivo consiste nel funzionamento dell'architettura di .NET Framework: il tipo DateTime è definito in mscorlib, la libreria più elementare di .NET. DateTime non è consentito l'attributo con 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 tramite l'attributo non può essere supportato. Il parser XAML dispone invece di un elenco di tipi che necessitano di elaborazione nativa ed elabora questi tipi con modalità analoghe all'elaborazione delle primitive effettive. Nel caso di DateTime, l'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 TypeConverterbase . La classe TypeConverter era presente nelle versioni di .NET Framework precedenti all'introduzione di XAML; in origine, uno degli scenari di TypeConverter consisteva nel fornire la conversione delle stringhe per gli editor delle proprietà nelle finestre di progettazione visiva.

Per XAML, il ruolo di TypeConverter viene esteso. In XAML, TypeConverter è la classe base che fornisce il supporto per determinate conversioni da stringa e in stringa. La conversione da stringa consente l'analisi di un valore dell'attributo di stringa da XAML. La conversione in stringa può permettere l'elaborazione di un valore di runtime di una particolare proprietà dell'oggetto in un attributo in XAML per la serializzazione.

TypeConverter definisce quattro membri rilevanti per la conversione da e in stringa per l'elaborazione XAML:

Di questi membri, il metodo più importante è ConvertFrom, che converte la stringa di input nel tipo di oggetto richiesto. È possibile implementare il metodo ConvertFrom per convertire una più vasta gamma di tipi nel tipo di destinazione previsto dal convertitore. Il metodo assolve quindi scopi che si estendono oltre quelli definiti per XAML, ad esempio il supporto delle conversioni in fase di esecuzione. Per quanto riguarda XAML, tuttavia, l'unico elemento importante è il percorso del codice che consente 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 è il passaggio di destinationType di Stringda parte del chiamante.

CanConvertTo e CanConvertFrom sono metodi di supporto usati quando un servizio esegue una query sulle funzionalità dell'implementazione di TypeConverter . È necessario implementare questi metodi per restituire true per i casi specifici del tipo supportati dai metodi di conversione equivalenti del convertitore. Per XAML, si tratta in genere del tipo String .

Informazioni relative alle impostazioni cultura e convertitori di tipi per XAML

Ogni implementazione di TypeConverter può interpretare in modo univoco il concetto di stringa valida per una conversione e può quindi usare o ignorare la descrizione del tipo passata come parametri. Una considerazione importante circa le impostazioni cultura e la conversione di tipi XAML: anche se l'uso di stringhe localizzabili come valori di attributo è supportato da XAML, non è possibile usare queste stringhe come input del convertitore di tipi con requisiti specifici per le impostazioni cultura. Questa limitazione è dovuta al fatto che i convertitori di tipi per i valori di attributo XAML implicano necessariamente un comportamento di elaborazione XAML basato su un'unica lingua che usa le impostazioni cultura en-US . Per altre informazioni sui motivi di progettazione per questa restrizione, vedi la specifica del linguaggio XAML ([MS-XAML]) o WPF Globalization and Localization Overview (Panoramica della globalizzazione e localizzazione WPF).

Un esempio delle problematiche che possono presentarsi con le impostazioni cultura è rappresentato dal separatore decimale per i numeri in formato stringa, che per alcune impostazioni cultura è la virgola anziché il punto. Quest'uso è in conflitto con il comportamento di molti convertitori di tipi esistenti, che prevede l'uso della virgola come delimitatore. Il passaggio di impostazioni cultura tramite xml:lang nel codice XAML adiacente non risolve il problema.

Implementazione di ConvertFrom

Per essere utilizzabile come implementazione di TypeConverter che supporti XAML, il metodo ConvertFrom per il convertitore deve accettare una stringa come parametro value . Se la stringa ha un formato valido e può essere convertita dall'implementazione di TypeConverter , l'oggetto restituito deve supportare un cast nel tipo previsto dalla proprietà. In caso contrario, l'implementazione ConvertFrom deve restituire null.

Ogni implementazione di TypeConverter può interpretare in modo univoco il concetto di stringa valida per una conversione e può anche usare o ignorare i contesti di descrizione del tipo o di impostazione cultura passati come parametri. Tuttavia, l'elaborazione della sintassi XAML di WPF potrebbe non passare i valori al contesto della descrizione del tipo in tutti i casi e potrebbe perfino non passare le impostazioni cultura basate su xml:lang.

Nota

Non usare le parentesi graffe ({}), in particolare la parentesi graffa di apertura ({), come elemento del formato stringa. Questi caratteri vengono usati esclusivamente come punti di ingresso e di uscita di una sequenza di estensione del markup.

È opportuno generare un'eccezione quando il convertitore di tipi deve avere accesso a un servizio XAML dal writer di oggetti servizi XAML .NET, ma la GetService chiamata eseguita sul 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 come parte delle funzionalità o della progettazione della classe, sarà necessario implementare ConvertTo.

Per essere utilizzabile come implementazione di TypeConverter che supporti XAML, il metodo ConvertTo per il convertitore deve accettare un'istanza del tipo (o un valore) supportata come parametro value . Quando il parametro destinationType è di tipo String, deve essere possibile eseguire il cast dell'oggetto restituito come String. La stringa restituita deve rappresentare un valore serializzato di value. In teoria, il formato di serializzazione scelto deve essere in grado di generare lo stesso valore che si otterrebbe se quella stringa venisse passata all'implementazione di ConvertFrom dello stesso convertitore, senza perdite significative di informazioni.

Se il valore non può essere serializzato o il convertitore non supporta la serializzazione, l'implementazione di ConvertTo deve restituire null e può generare un'eccezione. Tuttavia, se si generano eccezioni, sarà necessario segnalare l'impossibilità di usare tale conversione nell'implementazione di CanConvertTo in modo da supportare un controllo preventivo con CanConvertTo , che rappresenta la procedura consigliata per evitare eccezioni.

Se il parametro destinationType non è di tipo String, è possibile scegliere la gestione del convertitore. In genere viene ripristinata la gestione dell'implementazione di base, che nella forma base di ConvertTo genera un'eccezione specifica.

È opportuno generare un'eccezione quando il convertitore di tipi deve avere accesso a un servizio XAML dal writer di oggetti servizi XAML .NET, ma la GetService chiamata eseguita sul contesto non restituisce tale servizio.

Implementazione di CanConvertFrom

L'implementazione di CanConvertFrom deve restituire true per un oggetto sourceType di tipo String ; in caso contrario, deve rinviare all'implementazione di base. Non generare eccezioni da CanConvertFrom.

Implementazione di CanConvertTo

L'implementazione di CanConvertTo deve restituire true per un oggetto destinationType di tipo String; in caso contrario, deve rinviare all'implementazione di base. Non generare eccezioni da CanConvertTo.

Applicazione di TypeConverterAttribute

Affinché il convertitore di tipi personalizzato venga usato come convertitore di tipi agendo per una classe personalizzata da servizi XAML .NET, devi applicare l'oggetto TypeConverterAttribute alla definizione della classe. L'oggetto ConverterTypeName specificato tramite l'attributo deve corrispondere al nome di tipo del convertitore dei tipi personalizzato. Se si applica questo attributo, quando un processore XAML gestisce valori per cui il tipo di proprietà usa il tipo di classe personalizzato, può immettere stringhe e restituire istanze di oggetti.

Si può anche fornire un convertitore dei tipi per le singole proprietà. Anziché applicare un TypeConverterAttribute alla definizione della classe, applicarlo a una definizione della proprietà (la definizione principale, non le implementazioni di get/set al suo interno). Il tipo della proprietà deve corrispondere al tipo elaborato dal convertitore dei tipi personalizzato. Se questo attributo viene applicato, quando un processore XAML gestisce i valori di quella proprietà, può elaborare stringhe di input e restituire istanze di oggetti. 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 oggetto TypeConverterAttribute .

Per fornire un comportamento di conversione di tipi per un membro associato personalizzato, applicare TypeConverterAttribute al metodo della funzione di accesso Get del modello di implementazione per il membro associato.

Accesso al contesto del provider di servizi da un'implementazione dell'estensione di markup

I servizi disponibili sono gli stessi per qualsiasi convertitore di valori. L'unica differenza risiede nel modo in cui ogni convertitore di valori riceve il contesto del servizio. L'accesso ai servizi e i servizi disponibili sono illustrati nell'argomento Type Converters and Markup Extensions for XAML.

Convertitori di tipi nel flusso di nodi XAML

Se si usa un flusso del nodo XAML, l'azione o il risultato finale di un convertitore di tipi non è ancora eseguito. In un percorso di caricamento, la stringa dell'attributo che necessita di una conversione di tipi ai fini del caricamento resta sotto forma di valore testuale all'interno di un membro iniziale e di un membro finale. Il convertitore di tipi eventualmente necessario per questa operazione può essere determinato tramite la proprietà XamlMember.TypeConverter . Tuttavia, per ottenere un valore valido da XamlMember.TypeConverter è necessario avere un contesto dello schema XAML, che può accedere a queste informazioni tramite il membro sottostante, o il tipo del valore dell'oggetto usato dal membro. Il richiamo del comportamento di conversione di tipi richiede anche il contesto dello schema XAML poiché ciò richiede il mapping dei tipi e la creazione di un'istanza del convertitore.

Vedi anche