Definire tipi personalizzati da usare con i servizi XAML .NET

Quando definisci tipi personalizzati che sono oggetti business o sono tipi che non hanno una dipendenza da framework specifici, puoi seguire alcune procedure consigliate per XAML. Se segui queste procedure, i servizi XAML .NET e i relativi lettori XAML e writer XAML possono individuare le caratteristiche XAML del tipo e assegnargli una rappresentazione appropriata in un flusso di nodi XAML usando il sistema di tipi XAML. In questo argomento vengono descritte le procedure consigliate per definizioni di tipi, definizioni di membri e attributi CLR di tipi o membri.

Modelli di costruttore e definizioni di tipi per XAML

Per essere creata un'istanza come elemento oggetto in XAML, una classe personalizzata deve soddisfare i requisiti seguenti:

  • La classe personalizzata deve essere pubblica e deve esporre un costruttore pubblico senza parametri. Per alcune note riguardanti le strutture, vedere la sezione seguente.

  • La classe personalizzata non deve essere una classe annidata. Il "punto" aggiuntivo nel percorso full-name rende ambigua la divisione class-namespace e interferisce con altre funzionalità XAML, ad esempio le proprietà associate. Se è possibile creare un'istanza di un oggetto come elemento oggetto, l'oggetto creato può riempire il formato dell'elemento proprietà di qualsiasi proprietà che accetta l'oggetto come tipo sottostante.

È comunque possibile fornire valori oggetto per i tipi che non soddisfano questi criteri, se si abilita un convertitore di valori. Per altre informazioni, vedi Convertitori di tipi ed estensioni di markup per XAML.

Strutture

Le strutture sono sempre in grado di essere costruite in XAML, tramite la definizione CLR. Questo perché un compilatore CLR crea in modo implicito un costruttore senza parametri per una struttura. Questo costruttore inizializza tutti i valori delle proprietà in base alle impostazioni predefinite.

In alcuni casi, il comportamento di costruzione predefinito per una struttura non è auspicabile. Ciò potrebbe essere dovuto al fatto che la struttura è destinata a riempire i valori e a funzionare concettualmente come unione. Come unione, i valori contenuti potrebbero avere interpretazioni che si escludono a vicenda e pertanto nessuna delle relative proprietà è impostabile. Un esempio di tale struttura nel vocabolario WPF è GridLength. Tali strutture devono implementare un convertitore di tipi in modo che i valori possano essere espressi in forma di attributo, usando convenzioni di stringa che creano le diverse interpretazioni o modalità dei valori della struttura. La struttura deve esporre anche un comportamento simile per la costruzione del codice tramite un costruttore senza parametri.

Interfacce

Le interfacce possono essere usate come tipi sottostanti di membri. Il sistema di tipi XAML controlla l'elenco assegnabile e prevede che l'oggetto fornito come valore possa essere assegnato all'interfaccia. Non esiste alcun concetto di come l'interfaccia deve essere presentata come tipo XAML, purché un tipo assegnabile pertinente supporti i requisiti di costruzione XAML.

Metodi factory

I metodi factory sono una funzionalità XAML 2009. Modificano il principio XAML che gli oggetti devono avere costruttori senza parametri. I metodi factory non sono documentati in questo articolo. Vedere direttiva x:FactoryMethod.

Enumerazioni

Le enumerazioni hanno un comportamento di conversione dei tipi nativi XAML. I nomi delle costanti di enumerazione specificati in XAML vengono risolti in base al tipo di enumerazione sottostante e restituiscono il valore di enumerazione a un writer di oggetti XAML.

XAML supporta un utilizzo in stile flag per le enumerazioni applicate FlagsAttribute . Per altre informazioni, vedi Sintassi XAML in dettaglio. La sintassi XAML in dettaglio viene scritta per il pubblico WPF, ma la maggior parte delle informazioni contenute in questo argomento è rilevante per XAML che non è specifico di un framework di implementazione specifico.

Definizioni dei membri

I tipi possono definire i membri per l'utilizzo di XAML. È possibile che i tipi definisci membri utilizzabili da XAML anche se tale tipo specifico non è utilizzabile da XAML. Ciò è possibile a causa dell'ereditarietà CLR. Fino a quando un tipo che eredita il membro supporta l'utilizzo xaml come tipo e il membro supporta l'utilizzo XAML per il tipo sottostante o ha una sintassi XAML nativa disponibile, tale membro è utilizzabile da XAML.

Proprietà

Se definisci le proprietà come proprietà CLR pubblica usando i tipici modelli clr get e funzioni di accesso e set le parole chiave appropriate per il linguaggio, il sistema di tipi XAML può segnalare la proprietà come membro con le informazioni appropriate fornite per XamlMember le proprietà, ad esempio IsReadPublic e IsWritePublic.

Le proprietà specifiche possono abilitare una sintassi di TypeConverterAttributetesto applicando . Per altre informazioni, vedi Convertitori di tipi ed estensioni di markup per XAML.

In assenza di una sintassi di testo o di una conversione XAML nativa e in assenza di ulteriori informazioni indirette, ad esempio un utilizzo dell'estensione di markup, il tipo di una proprietà (TargetType nel sistema di tipi XAML) deve essere in grado di restituire un'istanza a un writer di oggetti XAML considerando il tipo di destinazione come tipo CLR.

Se si usa XAML 2009, l'estensione di markup x:Reference può essere usata per fornire valori se le considerazioni precedenti non vengono soddisfatte, ma questo è più di un problema di utilizzo rispetto a un problema di definizione del tipo.

evento

Se definisci eventi come evento CLR pubblico, il sistema di tipi XAML può segnalare l'evento come membro con IsEvent come true. Collegare i gestori eventi non rientra nell'ambito delle funzionalità dei servizi XAML .NET; il cablaggio viene lasciato a framework e implementazioni specifici.

Metodi

Il codice inline per i metodi non è una funzionalità XAML predefinita. Nella maggior parte dei casi, non fai riferimento direttamente ai membri del metodo da XAML e il ruolo dei metodi in XAML è solo quello di fornire supporto per modelli XAML specifici. La direttiva x:FactoryMethod è un'eccezione.

Campi

Le linee guida per la progettazione CLR sconsigliano i campi non statico. Per i campi statici, è possibile accedere ai valori dei campi statici solo tramite x:Static Markup Extension. In questo caso, non si esegue alcuna operazione speciale nella definizione CLR per esporre un campo per gli utilizzi x:Static .

Membri associabili

I membri associabili vengono esposti a XAML tramite un modello di metodo di accesso su un tipo di definizione. Il tipo di definizione stesso non deve essere utilizzabile da XAML come oggetto. In effetti, un modello comune consiste nel dichiarare una classe del servizio il cui ruolo è proprietario del membro associabile e implementare i comportamenti correlati, ma non serve altre funzioni, ad esempio una rappresentazione dell'interfaccia utente. Per le sezioni seguenti, il segnaposto PropertyName rappresenta il nome del membro associabile. Il nome deve essere valido nella grammatica XamlName.

Prestare attenzione alle collisioni di nomi tra questi modelli e altri metodi di un tipo. Se esiste un membro che corrisponde a uno dei modelli, può essere interpretato come un percorso di utilizzo dei membri associabile da un processore XAML anche se questa non era la tua intenzione.

Funzione di accesso GetPropertyName

La firma per la GetPropertyName funzione di accesso deve essere:

public static object GetPropertyName(object target)

  • L'oggetto target può essere specificato come tipo più specifico nell'implementazione. È possibile usarlo per definire l'ambito dell'utilizzo del membro collegabile; gli utilizzi all'esterno dell'ambito previsto genereranno eccezioni di cast non valide che vengono quindi rilevate da un errore di analisi XAML. Il nome target del parametro non è un requisito, ma è denominato target per convenzione nella maggior parte delle implementazioni.

  • Il valore restituito può essere specificato come tipo più specifico nell'implementazione.

Per supportare una TypeConverter sintassi di testo abilitata per l'utilizzo dell'attributo del membro associabile, applicare TypeConverterAttribute alla GetPropertyName funzione di accesso. L'applicazione get al anziché a set può sembrare non intuitiva. Tuttavia, questa convenzione può supportare il concetto di membri associabili di sola lettura che sono serializzabili, utile negli scenari di progettazione.

Funzione di accesso SetPropertyName

La firma per la SetPropertyName funzione di accesso deve essere:

public static void SetPropertyName(object target, object value)

  • L'oggetto target può essere specificato come tipo più specifico nell'implementazione, con la stessa logica e le stesse conseguenze descritte nella sezione precedente.

  • L'oggetto value può essere specificato come tipo più specifico nell'implementazione.

Tenere presente che il valore per questo metodo è l'input proveniente dall'utilizzo xaml, in genere nel formato attributo. Dal formato attributo deve essere presente il supporto del convertitore di valori per una sintassi di testo e l'attributo nella GetPropertyNamefunzione di accesso s.

Archivi membri associabili

I metodi della funzione di accesso in genere non sono sufficienti per fornire un mezzo per inserire i valori dei membri associabili in un oggetto grafico o per recuperare i valori dall'oggetto grafico e serializzarli correttamente. Per fornire questa funzionalità, gli target oggetti nelle firme della funzione di accesso precedenti devono essere in grado di archiviare i valori. Il meccanismo di archiviazione deve essere coerente con il principio del membro associabile che il membro è collegabile alle destinazioni in cui il membro associabile non è incluso nell'elenco dei membri. I servizi XAML .NET forniscono una tecnica di implementazione per gli archivi membri associabili tramite le IAttachedPropertyStore API e AttachablePropertyServices. IAttachedPropertyStore viene usato dai writer XAML per individuare l'implementazione dell'archivio e deve essere implementato nel tipo che rappresenta la target delle funzioni di accesso. Le API statiche AttachablePropertyServices vengono usate all'interno del corpo delle funzioni di accesso e fanno riferimento al membro associabile tramite il relativo AttachableMemberIdentifier.

L'attribuzione corretta di tipi, membri e assembly è importante per segnalare le informazioni sul sistema dei tipi XAML ai servizi XAML .NET. La segnalazione delle informazioni sul sistema dei tipi XAML è rilevante se si applica una delle situazioni seguenti:

  • Intendi usare i tuoi tipi con i sistemi XAML direttamente basati su lettori XAML e writer XAML dei servizi .NET.
  • Definisci o usi un framework XAML basato su lettori XAML e writer XAML.

Per un elenco di ogni attributo correlato a XAML pertinente per il supporto XAML dei tipi personalizzati, vedi Attributi CLR correlati a XAML per tipi e librerie personalizzati.

Utilizzo

L'utilizzo di tipi personalizzati richiede che l'autore del markup debba eseguire il mapping di un prefisso per l'assembly e lo spazio dei nomi CLR che contengono il tipo personalizzato. Questa procedura non è documentata in questo argomento.

Livello di accesso

XAML consente di caricare e creare istanze di tipi con internal un livello di accesso. Questa funzionalità viene fornita in modo che il codice utente possa definire i propri tipi e quindi creare un'istanza di tali classi dal markup che fa anche parte dello stesso ambito di codice utente.

Un esempio di WPF è ogni volta che il codice utente definisce un oggetto UserControl destinato a effettuare il refactoring di un comportamento dell'interfaccia utente, ma non come parte di qualsiasi possibile meccanismo di estensione che potrebbe essere implicito dichiarando la classe di supporto con public livello di accesso. Tale può UserControl essere dichiarato con internal accesso se il codice di supporto viene compilato nello stesso assembly da cui viene fatto riferimento come tipo XAML.

Per un'applicazione che carica XAML con attendibilità totale e usa XamlObjectWriter, il caricamento delle classi con internal livello di accesso è sempre abilitato.

Per un'applicazione che carica XAML con attendibilità parziale, puoi controllare le caratteristiche del livello di accesso usando l'API XamlAccessLevel . Inoltre, i meccanismi di rinvio (ad esempio il sistema di modelli WPF) devono essere in grado di propagare le autorizzazioni a livello di accesso e conservarle per le valutazioni di runtime finali; questo viene gestito internamente passando le XamlAccessLevel informazioni.

Implementazione WPF

WPF XAML usa un modello di accesso parzialmente attendibile in cui se BAML viene caricato con attendibilità parziale, l'accesso è limitato all'assembly AssemblyAccessTo che rappresenta l'origine BAML. Per il differimento, WPF usa IXamlObjectWriterFactory.GetParentSettings come meccanismo per passare le informazioni sul livello di accesso.

Nella terminologia XAML WPF un tipo interno è un tipo definito dallo stesso assembly che include anche il codice XAML di riferimento. Un tipo di questo tipo può essere mappato tramite uno spazio dei nomi XAML che omette deliberatamente la parte assembly= di un mapping, xmlns:local="clr-namespace:WPFApplication1"ad esempio . Se BAML fa riferimento a un tipo interno e tale tipo ha internal livello di accesso, viene generata una GeneratedInternalTypeHelper classe per l'assembly. Se si desidera evitare GeneratedInternalTypeHelper, è necessario usare public il livello di accesso oppure considerare la classe pertinente in un assembly separato e rendere tale assembly dipendente.

Vedi anche