Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Le estensioni di markup sono una tecnica XAML per ottenere un valore che non è una primitiva o un tipo XAML specifico. Per l'utilizzo degli attributi, le estensioni di markup usano la sequenza di caratteri nota di una parentesi graffa { di apertura per accedere all'ambito delle estensioni di markup e una parentesi graffa } di chiusura per uscire. Quando usi i servizi XAML .NET, puoi usare alcune delle estensioni di markup del linguaggio XAML predefinite dall'assembly System.Xaml. Puoi anche creare una sottoclasse derivata dalla classe MarkupExtension, definita in System.Xaml, e definire le tue estensioni di markup personalizzate. In alternativa, è possibile usare le estensioni di markup definite da un framework specifico se si fa già riferimento a tale framework.
Quando si accede a un utilizzo dell'estensione di markup, il writer di oggetti XAML può fornire servizi a una classe personalizzata MarkupExtension tramite un punto di connessione del servizio nell'override MarkupExtension.ProvideValue . I servizi possono essere usati per ottenere contesto sull'utilizzo, funzionalità specifiche del writer di oggetti, contesto dello schema XAML e così via.
Estensioni di markup definite da XAML
Diverse estensioni di markup vengono implementate dai servizi XAML .NET per il supporto del linguaggio XAML. Queste estensioni di markup corrispondono a parti della specifica di XAML come linguaggio. Questi sono in genere identificabili dal x: prefisso nella sintassi, come illustrato nell'utilizzo comune. Le implementazioni dei servizi XAML .NET per questi elementi del linguaggio XAML derivano tutti dalla MarkupExtension classe base.
Annotazioni
Il x: prefisso viene usato per il tipico mapping dello spazio dei nomi XAML dello spazio dei nomi del linguaggio XAML, nell'elemento radice di un ambiente di produzione XAML. Ad esempio, i modelli di progetto e di pagina di Visual Studio per vari framework specifici avviano un file XAML usando questo x: mapping. È possibile scegliere un token di prefisso diverso nel mapping dello spazio dei nomi XAML, ma questa documentazione presuppone il mapping predefinito x: come mezzo per identificare le entità che sono una parte definita dello spazio dei nomi XAML del linguaggio XAML, anziché uno spazio dei nomi XAML predefinito di un framework specifico o altri spazi dei nomi CLR o XML arbitrari.
x:Type
x:Type fornisce l'oggetto Type per il tipo denominato. Questa funzionalità viene usata più di frequente nei meccanismi di rinvio che usano il tipo CLR sottostante e la derivazione del tipo come moniker o identificatore di raggruppamento. Gli stili e i modelli WPF e il relativo utilizzo delle TargetType proprietà sono un esempio specifico. Per altre informazioni, vedere Estensione di markup x:Type.
x:Static
x:Static produce valori statici da entità di codice di tipo valore che non sono direttamente il tipo del valore di una proprietà, ma possono essere valutati in tale tipo. Ciò è utile per specificare valori che esistono già come costanti note in una definizione di tipo. Per ulteriori informazioni, vedere x:Static Markup Extension.
x:Null
x:Null specifica null come valore per un membro XAML. A seconda della progettazione di tipi specifici o di concetti di framework di dimensioni maggiori, null non è sempre un valore predefinito per una proprietà o il valore implicito di un attributo stringa vuoto. Per altre informazioni, vedere Estensione di markup x:Null.
x:Array
x:Array supporta la creazione di matrici generali nella sintassi XAML nei casi in cui il supporto della raccolta fornito da elementi di base e modelli di controllo non viene deliberatamente usato. Per altre informazioni, vedere Estensione di markup x:Array. In XAML 2009 in particolare, le matrici sono accessibili come primitive del linguaggio anziché come estensione. Per altre informazioni, vedi Funzionalità del linguaggio XAML 2009.
x:Reference
x:Reference fa parte di XAML 2009, un'estensione del set di linguaggio originale (2006).
x:Reference rappresenta un riferimento a un altro oggetto esistente in un oggetto grafico. L'oggetto è identificato dal x:Name. Per altre informazioni, vedere Estensione di markup x:Reference.
Altri x: Costrutti
Esistono altri x: costrutti per supportare le funzionalità del linguaggio XAML, ma non vengono implementati come estensioni di markup. Per altre informazioni, vedere spazio dei nomi XAML (x:) Funzionalità del linguaggio.
Classe base MarkupExtension
Per definire un'estensione di markup personalizzata in grado di interagire con le implementazioni predefinite di lettori XAML e writer XAML in System.Xaml, devi derivare una classe dalla classe astratta MarkupExtension . Tale classe ha un metodo di cui eseguire l'override, ovvero ProvideValue. Potrebbe anche essere necessario definire costruttori aggiuntivi per supportare argomenti per l'utilizzo dell'estensione di markup e le proprietà settable corrispondenti.
Tramite ProvideValue, un'estensione di markup personalizzata ha accesso a un contesto di servizio che segnala l'ambiente in cui l'estensione di markup viene richiamata da un processore XAML. Nel percorso di caricamento, si tratta in genere di un oggetto XamlObjectWriter. Nel percorso di salvataggio si tratta in genere di un oggetto XamlXmlWriter. Ogni report funge da classe di contesto del servizio XAML interno che implementa un modello di provider di servizi. Per altre informazioni sui servizi disponibili e su ciò che rappresentano, vedi Convertitori di tipi ed estensioni di markup per XAML.
La classe di estensione di markup deve avere un livello di accesso pubblico; i processori XAML devono poter instanziare sempre la classe di supporto dell'estensione di markup per utilizzarne i servizi.
Definizione del tipo di supporto per un'estensione di markup personalizzata
Quando usi i servizi XAML .NET o i framework basati su servizi XAML .NET, hai due opzioni per assegnare un nome al tipo di supporto dell'estensione di markup. Il nome del tipo è rilevante per il modo in cui i writer di oggetti XAML tentano di accedere e richiamare un tipo di supporto dell'estensione di markup quando riscontrano un utilizzo di estensione di markup in XAML. Usare una delle strategie di denominazione seguenti:
- Denominare il nome del tipo in modo che corrisponda esattamente al token di utilizzo del markup XAML. Ad esempio, per supportare un
{Collate ...}utilizzo dell'estensione, indicare ilCollatesupporto. - Denominare il nome del tipo come token stringa di utilizzo più il suffisso
Extension. Ad esempio, per supportare un{Collate ...}utilizzo dell'estensione, indicare ilCollateExtensionsupporto.
L'ordine di ricerca consiste nel cercare prima il nome della Extensionclasse con suffisso e quindi cercare il nome della classe senza il Extension suffisso.
Dal punto di vista dell'utilizzo del markup, incluso il Extension suffisso come parte dell'utilizzo è valido. Tuttavia, questo comportamento si comporta come se Extension fosse effettivamente parte del nome della classe e gli autori di oggetti XAML non riuscirebbero a risolvere una classe di supporto dell'estensione di markup per tale utilizzo se la classe di supporto non aveva il Extension suffisso.
Costruttore senza parametri
Per tutti i tipi di supporto delle estensioni di markup, dovresti esporre un costruttore pubblico senza parametri. Un costruttore senza parametri è necessario per qualsiasi caso in cui uno scrittore di oggetti XAML crea un'istanza dell'estensione di markup a partire dall'uso di un elemento oggetto. Il supporto dell'utilizzo degli elementi oggetto è una previsione equa per un'estensione di markup, in particolare per la serializzazione. Tuttavia, è possibile implementare un'estensione di markup senza un costruttore pubblico se si intende supportare solo gli utilizzi degli attributi dell'estensione di markup.
Se l'utilizzo dell'estensione di markup non include argomenti, il costruttore senza parametri è necessario per supportare l'utilizzo.
Modelli di costruttore e argomenti posizionali per un'estensione di markup personalizzata
Per un'estensione di markup con utilizzo di argomenti previsto, i costruttori pubblici devono corrispondere alle modalità di utilizzo previsto. In altre parole, se l'estensione di markup è progettata per richiedere un argomento posizionale come utilizzo valido, è necessario supportare un costruttore pubblico con un parametro di input che accetta l'argomento posizionale.
Si supponga, ad esempio, che l'estensione di markup supporti solo una modalità in cui è presente un argomento posizionale che ne rappresenta la Collate modalità, specificato come costante di CollationMode enumerazione. In questo caso, deve essere presente un costruttore con il formato seguente:
public Collate(CollationMode collationMode) {...}
A livello di base, gli argomenti passati a un'estensione di markup sono una stringa perché vengono inoltrati dai valori dell'attributo del markup. È possibile trasformare tutti gli argomenti in stringhe e gestire l'input a quel livello. Tuttavia, è possibile accedere a determinate elaborazioni che si verificano prima che gli argomenti dell'estensione di markup vengano passati alla classe di supporto.
L'elaborazione funziona concettualmente come se l'estensione di markup fosse un oggetto da creare e quindi vengono impostati i relativi valori membro. Ogni proprietà specificata da impostare viene valutata in modo simile a come un membro specificato può essere impostato su un oggetto creato quando viene analizzato XAML. Esistono due differenze importanti:
- Come indicato in precedenza, il tipo di estensione di markup supportata non deve avere un costruttore senza parametri per essere istanziato in XAML. La costruzione dell'oggetto viene posticipata fino a quando gli argomenti possibili nella sintassi del testo vengono tokenizzati e valutati come argomenti posizionali o denominati e il costruttore appropriato viene chiamato in quel momento.
- Gli utilizzi delle estensioni di markup possono essere annidati. L'estensione di markup più interna viene valutata per prima. Pertanto, è possibile presupporre tale utilizzo e dichiarare uno dei parametri di costruzione come un tipo che richiede un convertitore di valori (ad esempio un'estensione di markup) per produrre.
Nell'esempio precedente è stata illustrata una dipendenza da tale elaborazione. Il writer di oggetti XAML dei servizi XAML .NET trasforma i nomi delle costanti di enumerazione in valori enumerati, direttamente a livello nativo.
L'elaborazione della sintassi di un parametro posizionale in un'estensione di markup può basarsi anche su un convertitore di tipi associato al tipo presente nell'argomento di costruzione.
Gli argomenti vengono chiamati argomenti posizionali perché l'ordine in cui vengono rilevati i token nell'utilizzo corrisponde all'ordine posizionale del parametro del costruttore a cui sono assegnati. Si consideri ad esempio la firma del costruttore seguente:
public Collate(CollationMode collationMode, object collateThis) {...}
Un processore XAML prevede due argomenti posizionali per questa estensione di markup. Se è presente un utilizzo {Collate AlphaUp,{x:Reference circularFile}}, il token AlphaUp viene inviato al primo parametro e valutato come una costante di tipo enumerazione CollationMode. Il risultato dell'oggetto interno x:Reference viene inviato al secondo parametro e valutato come oggetto .
Nelle regole xaml specificate per la sintassi e l'elaborazione dell'estensione di markup, la virgola è il delimitatore tra gli argomenti, indipendentemente dal fatto che tali argomenti siano argomenti posizionali o argomenti denominati.
Duplicare l'arità degli argomenti posizionali
Se un writer di oggetti XAML rileva un utilizzo dell'estensione di markup con argomenti posizionali e sono presenti più argomenti del costruttore che accettano tale numero di argomenti (un'arità duplicata), che non è necessariamente un errore. Il comportamento dipende da un'impostazione del contesto dello schema XAML personalizzabile, SupportMarkupExtensionsWithDuplicateArity. Se SupportMarkupExtensionsWithDuplicateArity è true, un writer di oggetti XAML non deve generare un'eccezione solo per motivi di arità duplicata. Il comportamento al di là di tale punto non è definito rigorosamente. La supposizione fondamentale del design è che il contesto dello schema abbia disponibili le informazioni di tipo per i parametri specifici e possa tentare cast espliciti che corrispondano ai candidati duplicati per vedere quale firma possa essere la migliore corrispondenza. È possibile che venga generata un'eccezione se nessuna firma può superare i test imposti da quel particolare contesto dello schema in esecuzione su un writer di oggetti XAML.
Per impostazione predefinita, SupportMarkupExtensionsWithDuplicateArity è false nei servizi basati su CLR per XAML .NET. Pertanto, il valore predefinito XamlObjectWriter genera eccezioni se rileva un utilizzo dell'estensione di markup in cui è presente un'arità duplicata nei costruttori del tipo sottostante.
Argomenti denominati per un'estensione di markup personalizzata
Le estensioni di markup specificate da XAML possono anche usare una forma con argomenti nominati per l'utilizzo. Al primo livello di tokenizzazione, la sintassi del testo è divisa in argomenti. La presenza di un segno di uguale (=) all'interno di qualsiasi argomento identifica un argomento come argomento denominato. Tale argomento viene anche tokenizzato in una coppia nome/valore. Il nome in questo caso identifica una proprietà pubblica impostabile del tipo supportato dall'estensione di markup. Se si intende supportare l'utilizzo di argomenti denominati, dovresti fornire queste proprietà pubbliche impostabili. Le proprietà possono essere ereditate purché rimangano pubbliche.
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.
Utilizzo degli elementi di proprietà di un'estensione di markup
Gli scenari per gli utilizzi delle estensioni di markup sono spesso progettati per l'uso dell'estensione di markup nell'utilizzo degli attributi. Tuttavia, è anche possibile definire la classe di supporto per supportare l'utilizzo degli elementi di proprietà.
Per supportare l'utilizzo degli elementi di proprietà dell'estensione di markup, definire un costruttore pubblico senza parametri. Deve trattarsi di un costruttore di istanza non di un costruttore statico. Questo è necessario perché un processore XAML deve in genere richiamare il costruttore senza parametri su qualsiasi elemento oggetto che elabora dal markup e include classi di estensione di markup come elementi oggetto. Per gli scenari avanzati, è possibile definire percorsi di costruzione non predefiniti per le classi. Per altre informazioni, vedere x:FactoryMethod Directive.) Tuttavia, non è consigliabile usare questi modelli a scopo di estensione di markup perché rende molto più difficile l'individuazione del modello di utilizzo, sia per i progettisti che per gli utenti di markup non elaborato.
Attribuzione per un'estensione di markup personalizzata
Per supportare sia gli ambienti di progettazione che alcuni scenari di scrittura di oggetti XAML, è necessario assegnare un tipo di supporto per le estensioni di markup con diversi attributi CLR. Questi attributi segnalano l'utilizzo previsto dell'estensione di markup.
MarkupExtensionReturnTypeAttribute segnala le Type informazioni relative al tipo di oggetto restituito ProvideValue . In base alla sua firma pura, ProvideValue restituisce Object. Vari consumatori potrebbero volere informazioni più precise sul tipo restituito. Sono inclusi:
- Progettisti e IDE, che potrebbero essere in grado di fornire supporto consapevole dei tipi per gli utilizzi delle estensioni di markup.
- Implementazioni avanzate dei
SetMarkupExtensiongestori nelle classi di destinazione, che possono basarsi sulla reflection per determinare il tipo restituito di un'estensione di markup anziché fare riferimento a specifiche implementazioni note MarkupExtension con il loro nome.
Serializzazione degli utilizzi delle estensioni di markup
Quando un writer di oggetti XAML elabora l'utilizzo di un'estensione di markup e chiama ProvideValue, il contesto del suo precedente utilizzo come estensione di markup persiste nel flusso del nodo XAML, ma non nel grafo dell'oggetto. Nell'oggetto grafico viene mantenuto solo il valore. Se si hanno scenari di progettazione o altri motivi per rendere persistente l'utilizzo dell'estensione di markup originale nell'output serializzato, è necessario progettare un'infrastruttura personalizzata per tenere traccia degli utilizzi delle estensioni di markup dal flusso del nodo XAML del percorso di caricamento. È possibile implementare un meccanismo per ricreare gli elementi del flusso di nodi a partire dal percorso di caricamento e inviarli ai writer XAML per consentire la serializzazione nel percorso di salvataggio, sostituendo quindi il valore nella posizione corretta all'interno del flusso di nodi.
Le estensioni di markup nel flusso del nodo XAML
Se stai lavorando con uno stream di nodi XAML nel percorso di caricamento, un utilizzo dell'estensione di markup appare nello stream dei nodi come oggetto.
Se l'utilizzo dell'estensione di markup usa argomenti posizionali, viene rappresentato come un oggetto di avvio con un valore di inizializzazione. Come rappresentazione di testo approssimativo, il flusso del nodo è simile al seguente:
StartObject (XamlType è il tipo di definizione dell'estensione di markup, non il tipo restituito)
StartMember (nome dell'oggetto XamlMember è _InitializationText)
Value (value è l'argomento posizionale come stringa, inclusi i delimitatori intermedi)
EndMember
EndObject
L'uso di un'estensione di markup con argomenti denominati è rappresentato come un oggetto con membri che hanno i nomi pertinenti, ciascuno impostato con valori di stringa di testo.
In realtà, richiamare l'implementazione di un'estensione ProvideValue di markup richiede il contesto dello schema XAML perché richiede il mapping dei tipi e la creazione di un'istanza del tipo di supporto dell'estensione di markup. Questo è un motivo per cui gli utilizzi delle estensioni di markup vengono mantenuti in questo modo nei flussi del nodo dei servizi XAML .NET predefiniti. La parte lettore di un percorso di caricamento spesso non ha il contesto dello schema XAML necessario disponibile.
Se stai lavorando con un flusso di nodi XAML nel percorso di salvataggio, generalmente non c'è nulla in una rappresentazione di grafo di oggetti che possa indicare che l'oggetto da serializzare è stato originariamente fornito tramite l'utilizzo di un'estensione di markup e un risultato ProvideValue. Gli scenari che devono rendere persistenti gli utilizzi delle estensioni di markup per il round-tripping, mentre acquisiscono anche altre modifiche nel grafo di oggetti, devono ideare le proprie tecniche per mantenere le informazioni sull'utilizzo di un'estensione di markup dall'input XAML originale. Ad esempio, per ripristinare gli utilizzi dell'estensione di markup, potrebbe essere necessario usare il flusso del nodo nel percorso di salvataggio per ripristinare gli utilizzi delle estensioni di markup o eseguire un tipo di unione tra il codice XAML originale e il codice XAML arrotondato. Alcuni framework di implementazione XAML, ad esempio WPF, usano tipi intermedi (espressioni) per rappresentare i casi in cui gli utilizzi delle estensioni di markup hanno fornito i valori.
Vedere anche
.NET Desktop feedback