Descrizione dettagliata della sintassi XAML
In questo argomento vengono definiti i termini utilizzati per descrivere gli elementi della sintassi XAML. Questi termini vengono utilizzati spesso in tutta la documentazione, sia nella documentazione WPF specifica che nella documentazione relativa ad altri framework che utilizzano XAML o i concetti XAML di base consentiti dal supporto del linguaggio XAML a livello di System.Xaml. In questo argomento viene utilizzata la terminologia di base presentata nell'argomento Cenni preliminari su XAML (WPF).
Nel presente argomento sono contenute le seguenti sezioni.
- Specifica del linguaggio XAML
- XAML e CLR
- Sintassi per elementi oggetto
- Proprietà degli elementi oggetto
- Sintassi per attributi (proprietà)
- Sintassi degli elementi proprietà
- Sintassi per insiemi
- Proprietà di contenuto XAML
- Combinazione di proprietà di contenuto e sintassi per insiemi
- Spazi dei nomi XAML
- Estensioni di markup
- Proprietà associate
- Eventi associati
- Anatomia di un elemento radice XAML
- Utilizzi facoltativi e non consigliati di XAML
- Argomenti correlati
Specifica del linguaggio XAML
La terminologia della sintassi XAML presentata in questo argomento è anche definita o riportata nella specifica del linguaggio XAML. XAML è un linguaggio basato su XML e segue o amplia le regole strutturali XML. Parte della terminologia si fonda sulla terminologia comunemente utilizzata quando si descrive il linguaggio XML o il modello DOM (Document Object Model) XML.
Per ulteriori informazioni sulla specifica del linguaggio XAML, scaricare [MS-XAML] dall'Area download Microsoft.
XAML e CLR
XAML è un linguaggio di markup. common language runtime (CLR), come implicato dal nome, consente l'esecuzione del runtime. XAML non è intrinsecamente uno dei linguaggi comuni utilizzati direttamente dal runtime CLR. XAML può essere piuttosto considerato come un linguaggio che supporta un proprio sistema di tipi. Lo specifico sistema di analisi XAML utilizzato da WPF è basato su CLR e sul sistema dei tipi CLR. Per creare un'istanza di una rappresentazione in fase di esecuzione durante l'analisi di XAML per WPF, viene eseguito il mapping dei tipi XAML ai tipi CLR. Per questa ragione, nella parte rimanente di questo argomento dedicata alla sintassi saranno inclusi riferimenti al sistema dei tipi CLR, a differenza di quanto avviene nelle analoghe parti dedicate alla sintassi della specifica del linguaggio XAML. In base al livello della specifica del linguaggio XAML, è possibile eseguire il mapping dei tipi XAML a qualsiasi altro sistema di tipi, non necessariamente al sistema dei tipi CLR, ma ciò richiede la creazione e l'utilizzo di un parser XAML diverso.
Membri dei tipi ed ereditarietà delle classi
Le proprietà e gli eventi visualizzati come membri XAML di un tipo WPF vengono spesso ereditati dai tipi di base. Esaminare l'esempio riportato di seguito: <Button Background="Blue" .../>. La proprietà Background non è una proprietà dichiarata immediatamente nella classe Button, se si analizzano la definizione della classe, i risultati della reflection o la documentazione. Invece, Background è ereditata dalla classe Control di base.
Il comportamento dell'ereditarietà delle classi degli elementi XAML WPF rappresenta un allontanamento significativo dall'interpretazione del markup XML applicata in base allo schema. L'ereditarietà delle classi può diventare complessa, in particolare quando le classi di base intermedie sono astratte o quando sono interessate le interfacce. Questa è una delle ragioni per le quali il set di elementi XAML e dei relativi attributi consentiti è difficile da rappresentare con precisione e completezza utilizzando i tipi di schema che in genere sono impiegati per la programmazione XML, ad esempio il formato DTD o XSD. Un altro motivo consiste nel fatto che le funzionalità di estensibilità e di mapping di tipi del linguaggio XAML stesso precludono completezza di qualsiasi rappresentazione fissa dei tipi e dei membri consentiti.
Sintassi per elementi oggetto
La sintassi degli elementi oggetto è la sintassi del markup XAML che crea un'istanza di una classe o di una struttura CLR dichiarando un elemento XML. Questa sintassi è simile alla sintassi degli elementi di altri linguaggi di markup, ad esempio HTML. La sintassi degli elementi oggetto inizia con una parentesi angolare aperta (<), seguita immediatamente dal nome del tipo della classe o della struttura di cui viene creata un'istanza. Il nome del tipo può essere seguito da zero o più spazi ed è inoltre possibile dichiarare zero o più attributi nell'elemento oggetto, con uno o più spazi che separano ciascuna coppia nome="valore" dell'attributo. Infine, una delle seguenti condizioni deve essere soddisfatta:
L'elemento e il tag devono essere chiusi da una barra (/) seguita immediatamente da una parentesi angolare chiusa (>).
Il tag di apertura deve essere completato da una parentesi angolare chiusa (>). Altri elementi oggetto, elementi proprietà o il testo interno possono seguire il tag di apertura. Il contenuto esatto che è possibile inserire è generalmente vincolato dal modello a oggetti dell'elemento. Deve inoltre essere presente il tag di chiusura equivalente per l'elemento oggetto, opportunamente annidato e bilanciato con l'altra coppia di tag di apertura e chiusura.
In XAML implementato da .NET è incluso un set di regole per l'esecuzione del mapping degli elementi oggetto a tipi, degli attributi a proprietà o a eventi e degli spazi dei nomi XAML a spazi dei nomi CLR più assembly. Per WPF e .NET Framework, gli elementi oggetto XAML eseguono il mapping ai tipi Microsoft .NET definiti negli assembly a cui si fa riferimento, mentre gli attributi eseguono il mapping ai membri di tali tipi. Quando si fa riferimento a un tipo CLR in XAML, si può accedere anche ai membri ereditati di tale tipo.
Nell'esempio riportato di seguito viene illustrata la sintassi dell'elemento oggetto tramite cui viene creata una nuova istanza della classe Button e viene specificato un attributo Name e un valore per tale attributo:
<Button Name="CheckoutButton"/>
Nell'esempio riportato di seguito viene illustrata la sintassi dell'elemento oggetto che include anche la sintassi delle proprietà del contenuto XAML. Il testo interno contenuto verrà utilizzato per impostare la proprietà di contenuto XAML Text di TextBox.
<TextBox>This is a Text Box</TextBox>
Modelli di contenuto
Una classe potrebbe supportare un utilizzo come elemento oggetto XAML in termini di sintassi, tuttavia quell'elemento funzionerà correttamente in un'applicazione o in una pagina solo quando viene collocato in una posizione prevista di un modello di contenuto globale o di una struttura ad albero dell'elemento. Ad esempio, un oggetto MenuItem deve essere posizionato in genere solo come un figlio di una classe derivata MenuBase quale Menu. I modelli di contenuto per elementi specifici sono documentati come parte delle note nelle pagine relative alle classi per i controlli e le altre classi WPF che possono essere utilizzate come elementi XAML.
Proprietà degli elementi oggetto
Le proprietà di XAML vengono impostate tramite una varietà di sintassi possibili. La sintassi che sarà possibile utilizzare per una determinata proprietà varierà in base alle caratteristiche del sistema di tipi sottostante della proprietà che viene impostata.
Impostando i valori di proprietà, si aggiungono funzionalità o caratteristiche agli oggetti esistenti nell'oggetto grafico di runtime. Lo stato iniziale dell'oggetto creato da un elemento oggetto si basa sul comportamento predefinito del costruttore. In genere, l'applicazione utilizzerà un elemento diverso da un'istanza completamente predefinita di un dato oggetto.
Sintassi per attributi (proprietà)
La sintassi degli attributi è la sintassi del markup XAML mediante cui viene impostato un valore per una proprietà dichiarando un attributo in un elemento oggetto esistente. Il nome dell'attributo deve corrispondere al nome del membro CLR della proprietà della classe che supporta l'elemento oggetto pertinente. Il nome dell'attributo è seguito da un operatore di assegnazione (=). Il valore dell'attributo deve essere una stringa racchiusa tra virgolette.
Nota |
---|
È possibile utilizzare le virgolette alterne per inserire le virgolette letterali all'interno di un attributo.Per l'istanza è possibile utilizzare le virgolette singole per dichiarare una stringa contenente un carattere virgolette doppie.Indipendentemente dal fatto che si utilizzino le virgolette singole o quelle doppie, è necessario utilizzare una coppia corrispondente per l'apertura e la chiusura della stringa di valore dell'attributo.Per trovare una soluzione relativa alle restrizioni dei caratteri imposte da una qualsiasi sintassi XAML specifica, sono disponibili anche sequenze di escape o altre tecniche.Vedere Entità carattere XML e XAML. |
Affinché possa essere impostata tramite la sintassi degli attributi, è necessario che una proprietà sia pubblica e scrivibile. Il valore della proprietà nel sistema di tipi di supporto deve essere un tipo di valore o un tipo di riferimento di cui possa essere creata un'istanza o a cui possa essere fatto riferimento da parte di un processore XAML durante l'accesso al tipo di supporto rilevante.
Per gli eventi XAML WPF, l'evento a cui viene fatto riferimento come nome dell'attributo deve essere pubblico e deve disporre di un delegato pubblico.
La proprietà o l'evento deve essere un membro della classe o della struttura di cui viene creata un'istanza da parte dell'elemento oggetto contenitore.
Elaborazione dei valori di attributo
Il valore di stringa racchiuso tra le virgolette di apertura e chiusura viene elaborato da un processore XAML. Per le proprietà, il comportamento di elaborazione predefinito è determinato dal tipo della proprietà CLR sottostante.
Il valore di attributo viene riempito da uno degli elementi riportati di seguito, utilizzando questo ordine di elaborazione:
Se il processore XAML rileva una parentesi graffa o un elemento oggetto che deriva da MarkupExtension, l'estensione del markup a cui si fa riferimento viene valutata per prima, anziché esserne elaborato il valore come stringa, e viene utilizzato come valore il relativo oggetto restituito. In molti casi l'oggetto restituito da un'estensione del markup sarà un riferimento a un oggetto esistente o un'espressione che posticipa la valutazione alla fase di esecuzione, non un oggetto di cui è appena stata creata un'istanza.
Se la proprietà viene dichiarata con un oggetto TypeConverter con attributi o il tipo di valore di tale proprietà viene dichiarato con un oggetto TypeConverter con attributi, il valore di stringa dell'attributo viene inviato al convertitore di tipi come input di conversione e una nuova istanza dell'oggetto viene restituita dal convertitore.
Se non è presente alcun oggetto TypeConverter, viene tentata una conversione diretta al tipo della proprietà. Questo livello finale rappresenta una conversione diretta del valore nativo del parser tra tipi primitivi del linguaggio XAML o una ricerca dei nomi di costanti denominate in un'enumerazione, il parser accede quindi ai valori corrispondenti.
Valori di attributo dell'enumerazione
Le enumerazioni in XAML vengono elaborate intrinsecamente dai parser XAML e i relativi membri devono essere specificati indicando il nome stringa di una delle costanti denominate dell'enumerazione.
Per i valori di enumerazione non flag, il comportamento nativo consiste nell'elaborare la stringa di un valore di attributo e risolverla in uno dei valori di enumerazione. L'enumerazione non viene specificata nel formato Enumerazione.Valore, come avviene nel codice. Viene invece specificato solo Valore, mentre Enumerazione viene dedotta dal tipo della proprietà che si sta impostando. Se si specifica un attributo nel formato Enumerazione.Valore, non verrà risolto correttamente.
Per le enumerazioni basate su flag, il comportamento è basato sul metodo Enum.Parse. È possibile specificare più valori per un'enumerazione basata su flag separando ogni valore con una virgola. Tuttavia, non è possibile combinare valori di enumerazione non basati su flag. Ad esempio, non è possibile utilizzare la sintassi della virgola per tentare di creare un oggetto Trigger utilizzabile su più condizioni di un'enumerazione non flag:
<!--This will not compile, because Visibility is not a flagwise enumeration.-->
...
<Trigger Property="Visibility" Value="Collapsed,Hidden">
<Setter ... />
</Trigger>
...
Le enumerazioni basate su flag che supportano attributi impostabili in XAML sono rare in WPF. Tuttavia, StyleSimulations è un'enumerazione di questo tipo. Ad esempio, è possibile utilizzare la sintassi degli attributi basata su flag e delimitata da virgole per modificare l'esempio illustrato nella sezione Note per la classe Glyphs; StyleSimulations = "BoldSimulation" può diventare StyleSimulations = "BoldSimulation,ItalicSimulation". KeyBinding.Modifiers è un'altra proprietà in cui è possibile specificare più di un valore di enumerazione. Tuttavia, questa proprietà è un caso speciale, perché l'enumerazione ModifierKeys supporta il proprio convertitore di tipi. Il convertitore di tipi per i modificatori utilizza come delimitatore un segno più (+) anziché una virgola (). Questa conversione supporta la sintassi più tradizionale per rappresentare combinazioni di tasti nella programmazione Microsoft Windows, ad esempio "Ctrl+Alt."
Riferimenti ai nomi dei membri di eventi e proprietà
Quando si specifica un attributo, è possibile fare riferimento a qualsiasi proprietà o evento esistente come membro del tipo CLR di cui è stata creata un'istanza per l'elemento oggetto contenitore.
In alternativa, è possibile fare riferimento a una proprietà associata o a un evento associato, indipendente dall'elemento oggetto contenitore. Le proprietà associate saranno discusse in una sezione successiva.
È anche possibile denominare qualsiasi evento di qualsiasi oggetto accessibile tramite lo spazio dei nomi predefinito utilizzando un nome parzialmente qualificato nomeTipo.evento; questa sintassi supporta l'associazione di gestori per eventi indirizzati dove il gestore ha lo scopo di gestire un evento indirizzato da elementi figlio, ma nella tabella dei membri dell'elemento padre tale evento non è presente. Questa sintassi è simile alla sintassi di un evento associato, benché qui l'evento non sia un evento associato effettivo. In realtà, si fa riferimento a un evento con un nome completo. Per ulteriori informazioni, vedere Cenni preliminari sugli eventi indirizzati.
In alcuni scenari, talvolta i nomi delle proprietà vengono forniti come valore di un attributo, anziché come nome di attributo. Tale nome di proprietà può includere anche qualificatori, ad esempio la proprietà specificata nel formato tipoProprietario.nomeProprietàDipendenza. Questo scenario è comune quando si scrivono stili o modelli in XAML. Le regole di elaborazione per i nomi delle proprietà forniti come valore di attributo sono diverse e dipendono dal tipo della proprietà impostata o dai comportamenti di particolari sottosistemi WPF. Per informazioni dettagliate, vedere Applicazione di stili e modelli.
Un altro utilizzo per i nomi delle proprietà è rappresentato dal caso in cui un valore di attributo descrive una relazione proprietà-proprietà. Questa funzionalità viene utilizzata per l'associazione dati e per le destinazioni di storyboard e viene abilitata dalla classe PropertyPath e dal relativo convertitore di tipo. Per una descrizione più completa della semantica di ricerca, vedere Sintassi XAML di PropertyPath.
Sintassi degli elementi proprietà
La sintassi degli elementi proprietà si differenzia per certi versi dalle regole della sintassi XML di base per gli elementi. In XML, il valore di un attributo è una stringa di fatto, con la sola possibile variazione rappresentata dal formato di codifica della stringa utilizzato. In XAML, è possibile assegnare altri elementi oggetto come valore di una proprietà. Questa funzionalità viene abilitata dalla sintassi degli elementi proprietà. Anziché essere specificata come un attributo all'interno del tag di elemento, la proprietà viene specificata utilizzando un tag di elemento di apertura nel formato nomeTipoElemento.nomeProprietà, al cui interno viene specificato il valore della proprietà, quindi viene chiuso l'elemento proprietà.
In particolare, la sintassi inizia con una parentesi angolare aperta (<), seguita immediatamente dal nome del tipo della classe o della struttura in cui è contenuta la sintassi degli elementi proprietà. Questo è seguito da un punto singolo (.), dal nome di una proprietà, quindi da una parentesi angolare chiusa (>). Come nella sintassi degli attributi, tale proprietà deve essere presente all'interno dei membri pubblici dichiarati del tipo specificato. Il valore da assegnare alla proprietà è contenuto nell’elemento proprietà. In genere, il valore viene fornito come uno o più elementi oggetto, poiché la specifica di oggetti come valori rappresenta lo scenario per il quale la sintassi degli elementi proprietà è stata concepita. Infine, è necessario fornire un tag di chiusura equivalente che specifica la stessa combinazione nomeTipoElemento.nomeProprietà, opportunamente annidato e bilanciato con gli altri tag elemento.
Ad esempio, di seguito viene riportata la sintassi degli elementi proprietà per la proprietà ContextMenu di Button.
<Button>
<Button.ContextMenu>
<ContextMenu>
<MenuItem Header="1">First item</MenuItem>
<MenuItem Header="2">Second item</MenuItem>
</ContextMenu>
</Button.ContextMenu>
Right-click me!</Button>
Il valore nell'elemento proprietà può anche essere fornito come testo interno, nei casi in cui il tipo della proprietà specificato è un tipo di valore primitivo, ad esempio String o un'enumerazione in cui viene specificato un nome. Questi due utilizzi non sono molto comuni, poiché in ciascun caso potrebbe venire utilizzata anche una sintassi degli attributi più semplice. Uno scenario per riempire un elemento proprietà con una stringa riguarda le proprietà diverse dalla proprietà contenuto XAML, che vengono tuttavia utilizzate per la rappresentazione di testo dell'interfaccia utente e quando è necessario visualizzare in tale testo determinati elementi di spazio, quali gli avanzamenti riga. La sintassi degli attributi non può mantenere gli avanzamenti riga, a differenza della sintassi degli elementi proprietà a condizione che il mantenimento degli spazi significativi sia attivo (per informazioni dettagliate, vedere Elaborazione degli spazi vuoti in XAML). Un altro scenario consiste nella possibilità di applicare Direttiva x:Uid all'elemento proprietà e contrassegnare quindi il valore in esso contenuto come valore da localizzare nel BAML dell'output WPF o mediante altre tecniche.
Un elemento proprietà non è rappresentato nell'albero logico WPF. Rappresenta unicamente una sintassi particolare per l'impostazione di una proprietà e non dispone di un'istanza o oggetto che lo supporta. Per informazioni dettagliate sul concetto di albero logico, vedere Strutture ad albero in WPF.
Per le proprietà che supportano sia la sintassi per elementi proprietà, sia quella per elementi attributo, le due sintassi in genere hanno lo stesso risultato, sebbene sottigliezze quali la gestione degli spazi vuoti possano variare leggermente nei due casi.
Sintassi per insiemi
La specifica XAML richiede che le implementazioni del processore XAML identifichino le proprietà in cui il tipo di valore è un insieme. L'implementazione del processore XAML generale in .NET è basata su codice gestito e su CLR e identifica i tipi di insieme tramite una delle condizioni seguenti:
Il tipo implementa IList.
Il tipo implementa IDictionary.
Il tipo deriva da Array (per ulteriori informazioni sulle matrici in XAML, vedere Estensione del markup x:Array).
Se il tipo di una proprietà è un insieme, non è necessario specificare nel markup il tipo di insieme dedotto come elemento oggetto. Invece, gli elementi destinati a essere gli elementi dell'insieme vengono specificati come uno o più elementi figlio dell'elemento proprietà. Ognuno di questi elementi viene valutato in base a un oggetto durante il caricamento e aggiunto all'insieme chiamando il metodo Add dell'insieme implicito. Ad esempio, la proprietà Triggers di Style accetta il tipo di insieme specializzato TriggerCollection, il quale implementa IList. Non è tuttavia necessario creare un'istanza di un elemento oggetto TriggerCollection nel markup. Specificare invece uno o più elementi Trigger come elementi all'interno dell'elemento proprietà Style.Triggers, dove Trigger (o una classe derivata) è il tipo previsto come tipo di elemento per l'oggetto TriggerCollection fortemente tipizzato e implicito.
<Style x:Key="SpecialButton" TargetType="{x:Type Button}">
<Style.Triggers>
<Trigger Property="Button.IsMouseOver" Value="true">
<Setter Property = "Background" Value="Red"/>
</Trigger>
<Trigger Property="Button.IsPressed" Value="true">
<Setter Property = "Foreground" Value="Green"/>
</Trigger>
</Style.Triggers>
</Style>
Una proprietà può essere sia un tipo di insieme sia la proprietà di contenuto XAML per tale tipo e i tipi derivati, illustrata nella sezione successiva di questo argomento.
Un elemento insieme implicito crea un membro nella rappresentazione dell'albero logico, anche se non viene visualizzato nel markup come elemento. In genere, il costruttore del tipo padre crea le istanze per l'insieme che rappresenta una delle sue proprietà e l'insieme inizialmente vuoto viene aggiunto alla struttura ad albero di oggetti.
Nota |
---|
Le interfacce generiche di elenco e di dizionario, IList<T> e IDictionary<TKey, TValue>, non sono supportate per il rilevamento dell'insieme.Tuttavia, è possibile utilizzare la classe List<T> come classe di base, poiché implementa direttamente IList oppure Dictionary<TKey, TValue> come classe di base, poiché implementa direttamente IDictionary. |
Nelle pagine di riferimento .NET per i tipi di insieme, questa sintassi con l'omissione intenzionale dell'elemento oggetto per un insieme si nota occasionalmente nelle sezioni di sintassi XAML come sintassi per insiemi implicita.
Fatta eccezione per l'elemento radice, ogni elemento oggetto in un file XAML, annidato come elemento figlio di un altro elemento rappresenta in realtà uno o entrambi i casi seguenti: un membro di una proprietà dell'insieme implicita del relativo elemento padre o un elemento che specifica il valore della proprietà di contenuto XAML per l'elemento padre. Le proprietà di contenuto XAML verranno discusse in una sezione successiva. In altre parole, la relazione tra gli elementi padre e gli elementi figlio in una pagina di markup in realtà è un singolo oggetto nella radice; ogni elemento oggetto al di sotto della radice è una singola istanza che fornisce un valore di proprietà del padre oppure uno degli elementi all'interno di un insieme che è anche un valore della proprietà del tipo di insieme del padre. Questo concetto di radice singola è comune in XML e viene spesso rinforzato nel comportamento di API che caricano XAML quale Load.
Nell'esempio seguente viene illustrata una sintassi con l'elemento oggetto per un insieme (GradientStopCollection) specificato in modo esplicito.
<LinearGradientBrush>
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Offset="0.0" Color="Red" />
<GradientStop Offset="1.0" Color="Blue" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
Si noti che non sempre è possibile dichiarare in modo esplicito l'insieme. Ad esempio, il tentativo di dichiarare in modo esplicito TriggerCollection nell'esempio Triggers precedentemente illustrato non riuscirebbe. Per dichiarare in modo esplicito l'insieme è necessario che la classe dell'insieme supporti un costruttore predefinito e che TriggerCollection non disponga di un costruttore predefinito.
Proprietà di contenuto XAML
La sintassi del contenuto XAML è una sintassi che viene abilitata solo su classi che specificano ContentPropertyAttribute come parte della relativa dichiarazione di classe. ContentPropertyAttribute fa riferimento al nome della proprietà che è la proprietà di contenuto per tale tipo di elemento (incluse le classi derivate). In caso di elaborazione da parte di un processore XAML, qualsiasi elemento figlio o testo interno rilevato tra i tag di apertura e di chiusura dell'elemento oggetto verrà assegnato come valore della proprietà di contenuto XAML per l'oggetto. È consentito specificare elementi della proprietà espliciti per la proprietà di contenuto, ma questo utilizzo non è in genere illustrato nelle sezioni relative alla sintassi XAML del riferimento .NET. Questa tecnica esplicita/dettagliata ha un valore occasionale per la chiarezza o lo stile del markup, ma in genere il fine della proprietà di contenuto è semplificare il markup in modo che gli elementi correlati intuitivamente come padre-figlio possano essere annidati direttamente. I tag degli elementi proprietà per altre proprietà di un elemento non vengono assegnati come "contenuto" in base a una definizione rigida del linguaggio XAML, ma vengono prima elaborati nell'ordine di elaborazione del parser XAML e non sono considerati "contenuto".
I valori delle proprietà di contenuto XAML devono essere contigui
Il valore di una proprietà di contenuto XAML deve essere specificato completamente prima o completamente dopo qualsiasi altro elemento proprietà nell'elemento oggetto. Tale requisito è vero sia se il valore di una proprietà di contenuto XAML è specificato come stringa sia se è specificato come uno o più oggetti. Ad esempio, il markup seguente non effettua l'analisi:
<Button>I am a
<Button.Background>Blue</Button.Background>
blue button</Button>
Questa situazione non è consentita perché se questa sintassi fosse resa esplicita mediante l'utilizzo della sintassi per elementi proprietà per la proprietà di contenuto, la proprietà di contenuto verrebbe impostata due volte:
<Button>
<Button.Content>I am a </Button.Content>
<Button.Background>Blue</Button.Background>
<Button.Content> blue button</Button.Content>
</Button>
Un esempio simile è rappresentato dal caso in cui la proprietà di contenuto è un insieme e gli elementi figlio sono inframmezzati con elementi proprietà:
<StackPanel>
<Button>This example</Button>
<StackPanel.Resources>
<SolidColorBrush x:Key="BlueBrush" Color="Blue"/>
</StackPanel.Resources>
<Button>... is illegal XAML</Button>
</StackPanel>
Combinazione di proprietà di contenuto e sintassi per insiemi
Per accettare più di un singolo elemento oggetto come contenuto, il tipo della proprietà di contenuto deve essere specificamente un tipo di insieme. Analogamente alla sintassi degli elementi proprietà per i tipi di insieme, è necessario che un processore XAML identifichi quali tipi sono tipi di insieme. Se un elemento presenta una proprietà di contenuto XAML e il tipo della proprietà di contenuto XAML è un insieme, non è necessario specificare il tipo di insieme implicito nel markup come elemento oggetto, né specificare la proprietà di contenuto XAML come elemento proprietà. Pertanto, il modello di contenuto apparente nel markup può presentare più di un elemento figlio assegnato come contenuto. Di seguito viene riportata la sintassi del contenuto per una classe derivata Panel. Tutte le classi derivate da Panel stabiliscono che la proprietà di contenuto XAML sia Children, che richiede un valore di tipo UIElementCollection.
<Page
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
>
<StackPanel>
<Button>Button 1</Button>
<Button>Button 2</Button>
<Button>Button 3</Button>
</StackPanel>
</Page>
Si noti che né l'elemento proprietà per Children, né l'elemento per UIElementCollection è necessario nel markup. Si tratta di una funzionalità di progettazione di XAML, in base alla quale gli elementi contenuti in modo ricorsivo che definiscono un'UI vengono rappresentati in modo più intuitivo come una struttura ad albero di elementi annidati con relazioni padre-figlio immediate, senza tag di elementi proprietà o oggetti Collection estranei. Infatti, per caratteristiche di progettazione, non è possibile specificare in modo esplicito UIElementCollection nel markup come elemento oggetto. Poiché il solo utilizzo previsto è come insieme implicito, UIElementCollection non espone un costruttore predefinito pubblico e, di conseguenza, non è possibile crearne un'istanza come elemento oggetto.
Combinazione di elementi proprietà ed elementi oggetto in un oggetto con una proprietà di contenuto
La specifica XAML stabilisce che un processore XAML possa imporre che gli elementi oggetto utilizzati per riempire la proprietà di contenuto XAML all'interno di un elemento oggetto debbano essere contigui, non combinati. Questa restrizione che limita la combinazione di elementi proprietà e contenuto viene imposta dai processori XAML WPF.
È possibile disporre di un elemento oggetto figlio come primo markup all'interno di un elemento oggetto. Successivamente, è possibile introdurre elementi proprietà. In alternativa, è possibile specificare uno o più elementi proprietà, quindi elementi contenuto e, successivamente, altri elementi proprietà. Una volta inserito un elemento proprietà dopo il contenuto, non è possibile inserire altro contenuto, ma solo elementi proprietà.
Questo requisito di ordine tra elementi proprietà e contenuto non si applica al testo interno utilizzato come contenuto. Tuttavia, per uno stile di markup ottimale è bene mantenere contiguo il testo interno, poiché uno spazio vuoto significativo sarà difficile da rilevare visivamente nel markup se sono presenti elementi proprietà inframmezzati da testo interno.
Spazi dei nomi XAML
In nessuno degli esempi di sintassi precedenti è stato specificato uno spazio dei nomi XAML diverso da quello predefinito. Nelle applicazioni WPF tipiche lo spazio dei nomi XAML predefinito specificato è lo spazio dei nomi WPF. È possibile specificare spazi dei nomi XAML diversi dallo spazio dei nomi XAML predefinito e continuare a utilizzare sintassi simile. Ma in tutti i casi in cui viene denominata una classe che non è accessibile all'interno dello spazio dei nomi XAML predefinito, il nome della classe deve essere preceduto dal prefisso dello spazio dei nomi XAML mappato allo spazio dei nomi CLR corrispondente. Ad esempio, <custom:Example/> è la sintassi degli elementi oggetto per creare un'istanza della classe Example in cui lo spazio dei nomi CLR che contiene tale classe, ed eventualmente le informazioni sull'assembly esterno che contengono i tipi di supporto, è stato precedentemente mappato al prefisso custom.
Per ulteriori informazioni sugli spazi dei nomi XAML, vedere Spazi dei nomi XAML e mapping dello spazio dei nomi per XAML WPF.
Estensioni di markup
In XAML viene definita un'entità di programmazione di estensione di markup che costituisce un'alternativa alla normale gestione di valori di attributi di stringa o di elementi oggetto del processore XAML e posticipa l'elaborazione a una classe sottostante. Il carattere che identifica un'estensione di markup in un processore XAML quando si utilizza la sintassi degli attributi è la parentesi graffa di apertura ({), seguita da qualsiasi carattere a eccezione della parentesi graffa di chiusura (}). La prima stringa che segue la parentesi graffa di apertura deve fare riferimento alla classe che fornisce un particolare comportamento di estensione, in cui nel riferimento è possibile omettere la sottostringa "Estensione" se tale sottostringa fa parte del nome effettivo della classe. Dopodiché, potrebbe essere presente uno spazio singolo e, quindi, ogni carattere successivo viene utilizzato come input dall'implementazione dell'estensione, fino a quando non viene rilevata la parentesi graffa di chiusura.
L'implementazione XAML .NET utilizza la classe astratta MarkupExtension come base per tutte le estensioni di markup supportate da WPF nonché da altri framework o tecnologie. Le estensioni di markup che WPF implementa specificatamente sono spesso destinate a fornire un mezzo per fare riferimento ad altri oggetti esistenti o per rinviare riferimenti a oggetti che verranno valutati in fase di esecuzione. Ad esempio, una semplice associazione dati WPF viene realizzata specificando l'estensione di markup {Binding} al posto del valore che verrebbe generalmente accettato da una proprietà specificata. Molte delle estensioni di markup WPF consentono una sintassi degli attributo per le proprietà in cui una sintassi degli attributi non sarebbe altrimenti possibile. Ad esempio, un oggetto Style è un tipo di riferimento relativamente complesso che contiene una serie annidata di oggetti e di proprietà. Gli stili in WPF vengono definiti generalmente come una risorsa in un oggetto ResourceDictionary e, successivamente, viene fatto loro riferimento tramite una delle due estensioni di markup WPF che richiedono una risorsa. L'estensione di markup posticipa la valutazione del valore di proprietà a una ricerca di risorse e consente di specificare il valore della proprietà Style, che accetta il tipo Style, nella sintassi degli attributi come indicato di seguito:
<Button Style="{StaticResource MyStyle}">My button</Button>
StaticResource identifica la classe StaticResourceExtension che fornisce l'implementazione dell'estensione di markup. La stringa successiva MyStyle viene utilizzata come input per il costruttore StaticResourceExtension non predefinito, in cui il parametro accettato dalla stringa di estensione dichiara l'oggetto ResourceKey richiesto. MyStyle è previsto come valore x:Key di un oggetto Style definito come risorsa. L'utilizzo di Estensione del markup StaticResource richiede che la risorsa venga utilizzata per fornire il valore di proprietà Style tramite la logica di ricerca delle risorse statica in fase di caricamento.
Per ulteriori informazioni sulle estensioni di markup, vedere Estensioni di markup e XAML WPF. Per un elenco di riferimento delle estensioni di markup e di altre funzionalità di programmazione XAML consentite nell'implementazione XAML .NET generale, vedere Funzionalità del linguaggio dello spazio dei nomi XAML (x:). Per estensioni di markup specifiche di WPF, vedere Estensioni XAML WPF.
Proprietà associate
Le proprietà associate costituiscono un concetto di programmazione introdotto in XAML in base al quale le proprietà possono appartenere a un tipo specifico ed essere definite da esso, ma possono essere impostate come attributi o elementi proprietà su qualsiasi elemento. Lo scenario principale a cui sono destinate le proprietà associate è quello di consentire agli elementi figlio in una struttura del markup di fornire informazioni a un elemento padre senza la necessità di un modello a oggetti ampiamente condiviso tra tutti gli elementi. Viceversa, le proprietà associate possono essere utilizzate dagli elementi padre per fornire informazioni agli elementi figlio. Per ulteriori informazioni sullo scopo delle proprietà associate e su come creare proprietà associate personalizzate, vedere Cenni preliminari sulle proprietà associate.
Le proprietà associate utilizzano una sintassi che assomiglia per certi versi alla sintassi degli elementi proprietà, poiché anche in questo caso viene specificata una combinazione nomeTipo.nomeProprietà. Vi sono due differenze importanti:
È possibile utilizzare la combinazione nomeTipo.nomeProprietà anche quando si imposta una proprietà associata tramite la sintassi degli attributi. Le proprietà associate costituiscono l'unico caso in cui la qualifica del nome della proprietà è un requisito nella sintassi di un attributi.
È anche possibile utilizzare la sintassi degli elementi proprietà per le proprietà associate. Nella sintassi degli elementi proprietà tipica, tuttavia, nomeTipo è l'elemento oggetto che contiene l'elemento proprietà. Se si fa riferimento a una proprietà associata, nomeTipo è la classe che definisce la proprietà associata, non l'elemento oggetto contenitore.
Eventi associati
Gli eventi associati sono un altro concetto di programmazione introdotto in XAML mediante il quale è possibile definire gli eventi mediante un tipo specifico, ma è possibile associare i gestori a qualsiasi elemento oggetto. Nell'implementazione WPF, il tipo che definisce un evento associato è spesso un tipo statico che definisce un servizio e, in alcuni casi, gli eventi associati sono esposti dall'alias di un evento indirizzato in tipi che espongono il servizio. I gestori per gli eventi associati vengono specificati tramite la sintassi degli attributi. La sintassi degli attributi viene espansa per gli eventi associati per consentire l'utilizzo di nomeTipo.nomeEvento, in cui nomeTipo è la classe che fornisce le funzioni di accesso ai gestori eventi Add e Remove per l'infrastruttura degli eventi associati e nomeEvento è il nome dell'evento.
Anatomia di un elemento radice XAML
Nella tabella seguente viene mostrato un elemento radice standard XAML frammentato, in cui sono visualizzati gli attributi specifici di un elemento radice:
<Page |
Apertura dell'elemento oggetto dell'elemento radice |
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" |
Spazio dei nomi XAML predefinito (WPF) |
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" |
Spazio dei nomi XAML del linguaggio XAML |
x:Class="ExampleNamespace.ExampleCode" |
Dichiarazione di classe parziale che connette il markup a un qualsiasi code-behind definito per la classe parziale |
> |
Fine dell'elemento oggetto per la radice. L'oggetto non è ancora chiuso perché l'elemento contiene elementi figlio |
Utilizzi facoltativi e non consigliati di XAML
Nelle sezioni seguenti vengono descritti utilizzi di XAML supportati tecnicamente dai processori XAML, ma che generano un livello di dettaglio eccessivo o altri problemi estetici che interferiscono con file XAML leggibili quando si sviluppano applicazioni che contengono origini XAML.
Utilizzi facoltativi degli elementi proprietà
Gli utilizzi facoltativi degli elementi proprietà includono la scrittura esplicita di proprietà di contenuto degli elementi considerate implicite dal processore XAML. Ad esempio, quando si dichiara il contenuto di Menu, è possibile scegliere di dichiarare in modo esplicito l'insieme Items di Menu come tag dell'elemento proprietà <Menu.Items> e inserire ciascun oggetto MenuItem all'interno di <Menu.Items>, anziché utilizzare il comportamento implicito del processore XAML che stabilisce che tutti gli elementi figlio di un oggetto Menu debbano essere MenuItem e vengano posizionati nell'insieme Items. In alcuni casi gli utilizzi facoltativi possono consentire di chiarire visivamente la struttura dell'oggetto così come è rappresentata nel markup. In altri casi, un utilizzo esplicito di un elemento proprietà può evitare un markup tecnicamente funzionale ma visivamente confuso, ad esempio nel caso di estensioni di markup annidate in un valore di attributo.
Attributi qualificati nomeTipo.nomeMembro completi
Il formato nomeTipo.nomeMembro per un attributo può essere effettivamente utilizzato in modo più ampio rispetto agli eventi indirizzati. Tuttavia, in altre applicazioni tale formato è superfluo ed è opportuno evitarlo, anche solo per motivi di stile del markup e di leggibilità. Nell'esempio riportato di seguito, ognuno dei tre riferimenti all'attributo Background è completamente equivalente:
<Button Background="Blue">Background</Button>
<Button Button.Background="Blue">Button.Background</Button>
<Button Control.Background="Blue">Control.Background</Button>
È possibile utilizzare Button.Background poiché la ricerca qualificata per tale proprietà in Button è riuscita (Background è stato ereditato da Control) e Button è la classe dell'elemento oggetto o una classe di base. È possibile utilizzare Control.Background poiché la classe Control definisce effettivamente Background e Control è una classe di base Button.
Tuttavia, non è possibile utilizzare l'esempio di formato nomeTipo.nomeMembro riportato di seguito in cui sono visualizzati i commenti:
<!--<Button Label.Background="Blue">Does not work</Button> -->
Label è un'altra classe derivata di Control e se fosse stato specificato Label.Background all'interno di un elemento oggetto Label, questo utilizzo avrebbe avuto esito positivo. Tuttavia, poiché Label non è la classe o la classe di base di Button, il comportamento del processore XAML specificato consiste nell'elaborazione di Label.Background come proprietà associata. Label.Background non è una proprietà associata disponibile e questo utilizzo ha esito negativo.
Elementi proprietà nomeTipoBase.nomeMembro
Analogamente al funzionamento del formato nomeTipo.nomeMembro per la sintassi degli attributi, per la sintassi degli elementi proprietà è possibile utilizzare una sintassi nomeTipoBase.nomeMembro. Ad esempio, è possibile utilizzare la sintassi riportata di seguito:
<Button>Control.Background PE
<Control.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<GradientStop Color="Yellow" Offset="0.0" />
<GradientStop Color="LimeGreen" Offset="1.0" />
</LinearGradientBrush>
</Control.Background>
</Button>
In questo caso, l'elemento proprietà viene fornito come Control.Background anche se era contenuto in Button.
Analogamente al formato nomeTipo.nomeMembro per gli attributi, tuttavia, nomeTipoBase.nomeMembro non rappresenta uno stile di markup ottimale ed è opportuno evitarlo.
Vedere anche
Concetti
Cenni preliminari su XAML (WPF)
Cenni preliminari sulle proprietà di dipendenza
Classi XAML e personalizzate per WPF