Descrizione dettagliata della sintassi XAML
Questo argomento definisce i termini usati per descrivere gli elementi della sintassi XAML. Questi termini vengono usati spesso nella parte restante di questa documentazione, sia per la documentazione WPF in modo specifico che per gli altri framework che usano XAML o i concetti XAML di base abilitati dal supporto del linguaggio XAML a livello di System.Xaml. Questo argomento si espande sulla terminologia di base introdotta nell'argomento XAML in WPF.
Specifica del linguaggio XAML
La terminologia della sintassi XAML definita qui è definita o a cui viene fatto riferimento all'interno della specifica del linguaggio XAML. XAML è un linguaggio basato su XML e segue o si espande sulle regole strutturali XML. Una parte della terminologia viene condivisa da o si basa sulla terminologia comunemente usata quando si descrive il linguaggio XML o il modello a oggetti documento XML.
Per altre 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 implicito nel nome, abilita l'esecuzione di runtime. XAML non è uno dei linguaggi comuni usati direttamente dal runtime CLR. Puoi invece pensare a XAML come al supporto del proprio sistema di tipi. Il particolare sistema di analisi XAML usato da WPF è basato su CLR e sul sistema di tipi CLR. I tipi XAML vengono mappati ai tipi CLR per creare un'istanza di una rappresentazione in fase di esecuzione quando viene analizzato XAML per WPF. Per questo motivo, la parte restante della discussione sulla sintassi in questo documento includerà riferimenti al sistema di tipi CLR, anche se le discussioni sulla sintassi equivalenti nella specifica del linguaggio XAML non lo fanno. Per ogni livello di specifica del linguaggio XAML, è possibile eseguire il mapping dei tipi XAML a qualsiasi altro sistema di tipi, che non deve essere CLR, ma che richiederebbe la creazione e l'uso di un parser XAML diverso.
Membri dei tipi e dell'ereditarietà delle classi
Le proprietà e gli eventi visualizzati come membri XAML di un tipo WPF vengono spesso ereditati dai tipi di base. Si consideri ad esempio questo esempio: <Button Background="Blue" .../>
. La Background proprietà non è una proprietà dichiarata immediatamente nella Button classe , se si desidera esaminare la definizione della classe, i risultati della reflection o la documentazione. Viene invece Background ereditato dalla classe base Control .
Il comportamento di ereditarietà delle classi degli elementi XAML WPF è una differenza significativa rispetto a un'interpretazione applicata dallo schema del markup XML. L'ereditarietà della classe può diventare complessa, in particolare quando le classi di base intermedie sono astratte o quando sono coinvolte interfacce. Questo è un motivo per cui il set di elementi XAML e i relativi attributi consentiti è difficile rappresentare in modo accurato e completo i tipi di schema usati in genere per la programmazione XML, ad esempio il formato DTD o XSD. Un altro motivo è che l'estendibilità e le funzionalità di mapping dei tipi del linguaggio XAML stesso impediscono la completezza di qualsiasi rappresentazione fissa dei tipi e dei membri consentiti.
Sintassi degli elementi oggetto
La sintassi degli elementi oggetto è la sintassi di markup XAML che crea un'istanza di una classe o una struttura CLR dichiarando un elemento XML. Questa sintassi è simile alla sintassi degli elementi di altri linguaggi di markup, ad esempio HTML. La sintassi dell'elemento oggetto inizia con una parentesi uncinata sinistra (<), seguita immediatamente dal nome del tipo della classe o della struttura di cui viene creata un'istanza. Zero o più spazi possono seguire il nome del tipo e zero o più attributi possono anche essere dichiarati nell'elemento dell'oggetto, con uno o più spazi che separano ogni coppia nome attributo="value". Infine, una delle condizioni seguenti deve essere vera:
L'elemento e il tag devono essere chiusi da una barra (/) seguita immediatamente da una parentesi uncinata destra (>).
Il tag di apertura deve essere completato da una parentesi uncinata destra (>). Altri elementi oggetto, elementi di proprietà o testo interno possono seguire il tag di apertura. Esattamente il contenuto che può essere contenuto qui è in genere vincolato dal modello a oggetti dell'elemento. Anche il tag di chiusura equivalente per l'elemento oggetto deve esistere, con annidamento corretto e bilanciamento con altre coppie di tag di apertura e chiusura.
XAML implementato da .NET include un set di regole che eseguono il mapping degli elementi dell'oggetto in tipi, attributi in proprietà o eventi e spazi dei nomi XAML agli spazi dei nomi CLR più assembly. Per WPF e .NET, gli elementi oggetto XAML eseguono il mapping ai tipi .NET definiti negli assembly a cui si fa riferimento e gli attributi eseguono il mapping ai membri di tali tipi. Quando fai riferimento a un tipo CLR in XAML, hai accesso anche ai membri ereditati di quel tipo.
Ad esempio, l'esempio seguente è la sintassi degli elementi oggetto che crea un'istanza di una nuova istanza della Button classe e specifica anche un Name attributo e un valore per tale attributo:
<Button Name="CheckoutButton"/>
L'esempio seguente è la sintassi degli elementi oggetto che include anche la sintassi della proprietà del contenuto XAML. Il testo interno contenuto all'interno verrà usato per impostare la TextBox proprietà del contenuto XAML, Text.
<TextBox>This is a Text Box</TextBox>
Modelli di contenuto
Una classe potrebbe supportare un utilizzo come elemento oggetto XAML in termini di sintassi, ma tale elemento funzionerà correttamente in un'applicazione o in una pagina quando viene posizionato in una posizione prevista di un con modalità tenda l o albero degli elementi complessivo. Ad esempio, un MenuItem oggetto deve in genere essere inserito solo come elemento figlio di una MenuBase classe derivata, Menuad esempio . I con modalità tenda ls per elementi specifici sono documentati come parte delle osservazioni nelle pagine delle classi per i controlli e altre classi WPF che possono essere usate come elementi XAML.
Proprietà degli elementi oggetto
Le proprietà in XAML vengono impostate da un'ampia gamma di possibili sintassi. La sintassi che può essere usata per una determinata proprietà varia in base alle caratteristiche di sistema dei tipi sottostanti della proprietà impostata.
Impostando i valori delle proprietà, è possibile aggiungere caratteristiche o caratteristiche agli oggetti presenti nell'oggetto grafico dell'ora di esecuzione. Lo stato iniziale dell'oggetto creato da un elemento oggetto si basa sul comportamento del costruttore senza parametri. In genere, l'applicazione userà qualcosa di diverso da un'istanza completamente predefinita di qualsiasi oggetto specificato.
Sintassi per attributi (proprietà)
La sintassi dell'attributo è la sintassi di markup XAML che imposta un valore per una proprietà dichiarando un attributo su un elemento oggetto esistente. Il nome dell'attributo deve corrispondere al nome del membro CLR della proprietà della classe che restituisce 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 usare virgolette alternate per inserire una virgoletta letterale all'interno di un attributo. Ad esempio, è possibile usare virgolette singole come mezzo per dichiarare una stringa che contiene un carattere virgolette doppie al suo interno. Se si usano virgolette singole o doppie, è consigliabile usare una coppia corrispondente per aprire e chiudere la stringa del valore dell'attributo. Sono disponibili anche sequenze di escape o altre tecniche per aggirare le restrizioni dei caratteri imposte da una particolare sintassi XAML. Vedi Entità carattere XML e XAML.
Per poter essere impostata tramite la sintassi degli attributi, una proprietà deve essere pubblica e deve essere scrivibile. Il valore della proprietà nel sistema di tipi di supporto deve essere un tipo valore o deve essere un tipo riferimento che può essere creato o a cui fa riferimento un processore XAML quando accede al tipo di supporto pertinente.
Per gli eventi XAML WPF, l'evento a cui viene fatto riferimento come nome dell'attributo deve essere pubblico e avere un delegato pubblico.
La proprietà o l'evento deve essere un membro della classe o della struttura di cui viene creata un'istanza dall'elemento oggetto contenitore.
Elaborazione dei valori degli attributi
Il valore stringa contenuto tra 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 dell'attributo viene compilato in base a una delle condizioni seguenti, usando questo ordine di elaborazione:
Se il processore XAML rileva una parentesi graffa o un elemento oggetto che deriva da MarkupExtension, l'estensione di markup a cui si fa riferimento viene valutata prima anziché elaborare il valore come stringa e l'oggetto restituito dall'estensione di markup viene usato come valore. In molti casi l'oggetto restituito da un'estensione di markup sarà un riferimento a un oggetto esistente o un'espressione che rinvia la valutazione fino alla fase di esecuzione e non è un nuovo oggetto di cui è stata creata un'istanza.
Se la proprietà viene dichiarata con un attributo TypeConvertero il tipo di valore di tale proprietà viene dichiarato con un attributo TypeConverter, il valore stringa dell'attributo viene inviato al convertitore di tipi come input di conversione e il convertitore restituirà una nuova istanza dell'oggetto.
Se non TypeConverterè presente , viene tentata una conversione diretta nel tipo di proprietà. Questo livello finale è una conversione diretta al valore nativo del parser tra i tipi primitivi del linguaggio XAML o un controllo dei nomi delle costanti denominate in un'enumerazione (il parser accede quindi ai valori corrispondenti).
Valori degli attributi di enumerazione
Le enumerazioni in XAML vengono elaborate intrinsecamente dai parser XAML e i membri di un'enumerazione devono essere specificati specificando il nome della 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. Non si specifica l'enumerazione nel formato Enumeration.Valore, come si fa nel codice. Al contrario, si specifica solo Value e l'enumerazione viene dedotta dal tipo della proprietà impostata. Se si specifica un attributo nell'enumerazione .Modulo valore, non verrà risolto correttamente.
Per le enumerazioni flag per flag, il comportamento è basato sul Enum.Parse metodo . È possibile specificare più valori per un'enumerazione flag per flag separando ogni valore con una virgola. Tuttavia, non è possibile combinare valori di enumerazione che non sono flag per flag. Ad esempio, non è possibile usare la sintassi della virgola per tentare di creare un Trigger oggetto che agisca su più condizioni di un'enumerazione non di tipo flag:
<!--This will not compile, because Visibility is not a flagwise enumeration.-->
...
<Trigger Property="Visibility" Value="Collapsed,Hidden">
<Setter ... />
</Trigger>
...
Le enumerazioni flag per flag che supportano gli attributi che sono impostabili in XAML sono rare in WPF. Tuttavia, un'enumerazione di questo tipo è StyleSimulations. È possibile, ad esempio, usare la sintassi dell'attributo flagwise delimitato da virgole per modificare l'esempio fornito nella sezione Osservazioni per la Glyphs classe. StyleSimulations = "BoldSimulation"
Potrebbe diventare StyleSimulations = "BoldSimulation,ItalicSimulation"
. KeyBinding.Modifiers è un'altra proprietà in cui è possibile specificare più valori 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 usa un segno più (+) come delimitatore anziché una virgola (,). Questa conversione supporta la sintassi più tradizionale per rappresentare le combinazioni di tasti nella programmazione di Microsoft Windows, ad esempio "CTRL+ALT".
Proprietà e riferimenti al nome del membro dell'evento
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, indipendentemente dall'elemento oggetto contenitore. Le proprietà associate vengono descritte in una sezione futura.
È anche possibile assegnare un nome a qualsiasi evento da qualsiasi oggetto accessibile tramite lo spazio dei nomi predefinito usando un typeName.nome parzialmente completo dell'evento . Questa sintassi supporta il collegamento di gestori per gli eventi indirizzati in cui il gestore è destinato a gestire il routing degli eventi dagli elementi figlio, ma l'elemento padre non dispone anche di tale evento nella relativa tabella dei membri. Questa sintassi è simile a una sintassi di evento associata, ma l'evento qui non è un vero evento associato. Si fa invece riferimento a un evento con un nome completo. Per altre informazioni, vedere Cenni preliminari sugli eventi indirizzati.
Per alcuni scenari, i nomi delle proprietà vengono talvolta forniti come valore di un attributo, anziché come nome dell'attributo. Tale nome di proprietà può includere anche qualificatori, ad esempio la proprietà specificata nel formato ownerType.dependencyPropertyName. Questo scenario è comune quando si scrivono stili o modelli in XAML. Le regole di elaborazione per i nomi delle proprietà fornite come valore di attributo sono diverse e sono regolate dal tipo della proprietà impostata o dai comportamenti di determinati sottosistemi WPF. Per informazioni dettagliate, vedere Applicazione di stili e modelli.
Un altro utilizzo per i nomi delle proprietà è quando un valore di attributo descrive una relazione proprietà-proprietà. Questa funzionalità viene usata per il data binding e per le destinazioni dello storyboard ed è abilitata dalla classe e dal PropertyPath relativo convertitore di tipi. Per una descrizione più completa della semantica di ricerca, vedi Sintassi XAML di PropertyPath.
Sintassi per gli elementi proprietà
La sintassi degli elementi proprietà è una sintassi che differisce in qualche modo dalle regole di sintassi XML di base per gli elementi. In XML, il valore di un attributo è una stringa de facto, con l'unica variante possibile che viene usato il formato di codifica della stringa. In XAML puoi assegnare altri elementi oggetto come valore di una proprietà. Questa funzionalità è abilitata dalla sintassi dell'elemento proprietà. Anziché la proprietà specificata come attributo all'interno del tag di elemento, la proprietà viene specificata usando un tag di elemento di apertura in elementTypeName.form propertyName , il valore della proprietà viene specificato all'interno e quindi l'elemento della proprietà viene chiuso.
In particolare, la sintassi inizia con una parentesi uncinata sinistra (<), seguita immediatamente dal nome del tipo della classe o della struttura in cui è contenuta la sintassi dell'elemento proprietà. Viene seguito immediatamente da un singolo punto (.), quindi dal nome di una proprietà, quindi da una parentesi uncinata destra (>). Come per la sintassi dell'attributo, tale proprietà deve esistere all'interno dei membri pubblici dichiarati del tipo specificato. Il valore da assegnare alla proprietà è contenuto nell'elemento property. In genere, il valore viene assegnato come uno o più elementi oggetto, perché specificando gli oggetti come valori è lo scenario che la sintassi degli elementi di proprietà è destinata a risolvere. Infine, un tag di chiusura equivalente che specifica lo stesso elementTypeName.è necessario specificare la combinazione propertyName , in modo corretto nell'annidamento e nel bilanciamento con altri tag di elemento.
Ad esempio, di seguito è riportata la sintassi degli elementi di proprietà per la ContextMenu proprietà di un oggetto 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 all'interno di un elemento della proprietà può essere assegnato anche come testo interno, nei casi in cui il tipo di proprietà specificato è un tipo di valore primitivo, ad esempio String, o un'enumerazione in cui viene specificato un nome. Questi due utilizzi sono un po ' insoliti, perché ognuno di questi casi potrebbe anche usare una sintassi di attributo più semplice. Uno scenario per riempire un elemento di proprietà con una stringa è per le proprietà che non sono la proprietà del contenuto XAML, ma vengono comunque usate per la rappresentazione del testo dell'interfaccia utente e sono necessari particolari elementi di spazi vuoti, ad esempio i avanzamenti riga, per essere visualizzati nel testo dell'interfaccia utente. La sintassi degli attributi non può mantenere gli avanzamenti di riga, ma la sintassi degli elementi di proprietà può, purché sia attiva la conservazione significativa dello spazio vuoto (per informazioni dettagliate, vedere Elaborazione dello spazio vuoto in XAML). Un altro scenario è in modo che x:Uid Directive possa essere applicato all'elemento della proprietà e contrassegnare quindi il valore all'interno come valore che deve essere localizzato nell'output BAML WPF o da altre tecniche.
Un elemento proprietà non è rappresentato nell'albero logico WPF. Un elemento di proprietà è solo una sintassi specifica per l'impostazione di una proprietà e non è un elemento che dispone di un'istanza o di un oggetto che lo sostiene. Per informazioni dettagliate sul concetto di albero logico, vedere Alberi in WPF.
Per le proprietà in cui sono supportate sia la sintassi degli attributi che degli elementi di proprietà, le due sintassi hanno in genere lo stesso risultato, anche se le sottigliezze come la gestione degli spazi vuoti possono variare leggermente tra le sintassi.
Sintassi per raccolte
La specifica XAML richiede implementazioni del processore XAML per identificare le proprietà in cui il tipo di valore è una raccolta. L'implementazione generale del processore XAML in .NET si basa su codice gestito e CLR e identifica i tipi di raccolta tramite uno dei seguenti:
Il tipo implementa IList.
Il tipo implementa IDictionary.
Il tipo deriva da Array (per altre informazioni sulle matrici in XAML, vedere x:Array Markup Extension.)
Se il tipo di una proprietà è una raccolta, non è necessario specificare il tipo di raccolta dedotto nel markup come elemento oggetto. Gli elementi destinati a diventare gli elementi dell'insieme vengono invece specificati come uno o più elementi figlio dell'elemento proprietà. Ogni elemento di questo tipo viene valutato in un oggetto durante il caricamento e aggiunto alla raccolta chiamando il Add
metodo della raccolta implicita. Ad esempio, la Triggers proprietà di Style accetta il tipo di TriggerCollectionraccolta specializzato , che implementa IList. Non è necessario creare un'istanza di un TriggerCollection elemento oggetto nel markup. È invece necessario specificare uno o più Trigger elementi come elementi all'interno dell'elemento Style.Triggers
della proprietà, dove Trigger (o una classe derivata) è il tipo previsto come tipo di elemento per l'elemento fortemente tipizzato e implicito TriggerCollection.
<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 raccolta che la proprietà del contenuto XAML per il tipo e i tipi derivati, illustrati nella sezione successiva di questo argomento.
Un elemento di raccolta implicito crea un membro nella rappresentazione ad albero logico, anche se non viene visualizzato nel markup come elemento. In genere il costruttore del tipo padre esegue l'istanza per la raccolta che è una delle relative proprietà e la raccolta inizialmente vuota diventa parte dell'albero degli oggetti.
Nota
Le interfacce generiche di elenco e dizionario (IList<T> e IDictionary<TKey,TValue>) non sono supportate per il rilevamento delle raccolte. Tuttavia, è possibile usare la List<T> classe come classe di base, perché implementa IList direttamente o Dictionary<TKey,TValue> come classe base, perché implementa IDictionary direttamente.
Nelle pagine di riferimento .NET per i tipi di raccolta, questa sintassi con l'omissione intenzionale dell'elemento oggetto per una raccolta viene occasionalmente annotata nelle sezioni della sintassi XAML come sintassi di raccolta implicita.
Ad eccezione dell'elemento radice, ogni elemento oggetto in un file XAML annidato come elemento figlio di un altro elemento è in realtà un elemento che è uno o entrambi i casi seguenti: un membro di una proprietà di raccolta implicita del relativo elemento padre o un elemento che specifica il valore della proprietà del contenuto XAML per l'elemento padre (le proprietà del contenuto XAML verranno illustrate in una sezione futura). In altre parole, la relazione di elementi padre e elementi figlio in una pagina di markup è in realtà un singolo oggetto nella radice e ogni elemento oggetto sotto la radice è una singola istanza che fornisce un valore di proprietà dell'elemento padre o uno degli elementi all'interno di un insieme che è anche un valore della proprietà di tipo raccolta dell'elemento padre. Questo concetto a radice singola è comune con XML ed è spesso rafforzato nel comportamento delle API che caricano XAML, Loadad esempio .
L'esempio seguente è una sintassi con l'elemento oggetto per una raccolta (GradientStopCollection) specificata 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 la raccolta. Ad esempio, il tentativo di dichiarare TriggerCollection in modo esplicito nell'esempio illustrato Triggers in precedenza avrà esito negativo. Per dichiarare in modo esplicito la raccolta, la classe di raccolta deve supportare un costruttore senza parametri e TriggerCollection non dispone di un costruttore senza parametri.
Proprietà di contenuto XAML
La sintassi del contenuto XAML è una sintassi abilitata solo nelle classi che specificano come ContentPropertyAttribute parte della dichiarazione di classe. Fa ContentPropertyAttribute riferimento al nome della proprietà che rappresenta la proprietà content per quel tipo di elemento (incluse le classi derivate). Quando viene elaborato da un processore XAML, tutti gli elementi figlio o il testo interno trovati tra i tag di apertura e chiusura dell'elemento oggetto verranno assegnati come valore della proprietà contenuto XAML per tale oggetto. È possibile specificare elementi di proprietà espliciti per la proprietà content, ma questo utilizzo non viene in genere visualizzato nelle sezioni della sintassi XAML nelle informazioni di riferimento su .NET. La tecnica esplicita/dettagliata ha un valore occasionale per la chiarezza del markup o per quanto riguarda lo stile di markup, ma in genere lo scopo di una proprietà di contenuto è semplificare il markup in modo che gli elementi correlati in modo intuitivo come padre-figlio possano essere annidati direttamente. I tag degli elementi di proprietà per altre proprietà su un elemento non vengono assegnati come "contenuto" per una definizione rigorosa del linguaggio XAML; vengono elaborati in precedenza nell'ordine di elaborazione del parser XAML e non vengono considerati "contenuti".
I valori delle proprietà del contenuto XAML devono essere contigui
Il valore di una proprietà del contenuto XAML deve essere assegnato interamente prima o interamente dopo qualsiasi altro elemento di proprietà su tale elemento oggetto. Questo vale se il valore di una proprietà del contenuto XAML viene specificato come stringa o come uno o più oggetti. Ad esempio, il markup seguente non analizza:
<Button>I am a
<Button.Background>Blue</Button.Background>
blue button</Button>
Questo è essenzialmente illegale perché se questa sintassi è stata resa esplicita usando la sintassi degli elementi di proprietà per la proprietà content, la proprietà content verrà 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 analogamente non valido è se la proprietà content è una raccolta e gli elementi figlio sono interspersi con gli elementi della 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 raccolte
Per accettare più di un singolo elemento oggetto come contenuto, il tipo della proprietà del contenuto deve essere in particolare un tipo di raccolta. Analogamente alla sintassi degli elementi di proprietà per i tipi di raccolta, un processore XAML deve identificare i tipi di raccolta. Se un elemento ha una proprietà del contenuto XAML e il tipo della proprietà del contenuto XAML è una raccolta, non è necessario specificare il tipo di raccolta implicito nel markup come elemento oggetto e la proprietà del contenuto XAML non deve essere specificata come elemento di proprietà. Pertanto, il con modalità tenda l apparente nel markup può ora avere più di un elemento figlio assegnato come contenuto. Di seguito è riportata la sintassi del contenuto per una Panel classe derivata. Tutte le Panel classi derivate stabiliscono la proprietà del contenuto XAML come Children, che richiede un valore di tipo UIElementCollection.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<StackPanel>
<Button>Button 1</Button>
<Button>Button 2</Button>
<Button>Button 3</Button>
</StackPanel>
</Page>
Si noti che nel markup non è necessario né l'elemento della proprietà per Children né l'elemento UIElementCollection per . Si tratta di una funzionalità di progettazione di XAML in modo che gli elementi contenuti in modo ricorsivo che definiscono un'interfaccia utente siano rappresentati in modo più intuitivo come albero di elementi annidati con relazioni immediate tra elementi padre-figlio, senza tag di elemento proprietà o oggetti raccolta. Non è infatti UIElementCollection possibile specificare in modo esplicito nel markup come elemento oggetto, per impostazione predefinita. Poiché l'unico utilizzo previsto è una raccolta implicita, UIElementCollection non espone un costruttore pubblico senza parametri e pertanto non può essere creata un'istanza come elemento oggetto.
Combinazione di elementi di proprietà ed elementi oggetto in un oggetto con una proprietà Content
La specifica XAML dichiara che un processore XAML può imporre che gli elementi oggetto usati per riempire la proprietà del contenuto XAML all'interno di un elemento oggetto devono essere contigui e non devono essere misti. Questa restrizione contro la combinazione di elementi di proprietà e contenuto viene applicata dai processori XAML WPF.
È possibile avere un elemento oggetto figlio come primo markup immediato all'interno di un elemento oggetto. È quindi possibile introdurre elementi di proprietà. In alternativa, è possibile specificare uno o più elementi di proprietà, quindi il contenuto e altri elementi di proprietà. Tuttavia, una volta che un elemento di proprietà segue il contenuto, non è possibile introdurre altri contenuti, è possibile aggiungere solo elementi di proprietà.
Questo requisito per l'ordine degli elementi content/property non si applica al testo interno usato come contenuto. Tuttavia, è comunque un buon stile di markup per mantenere contiguo il testo interno, perché uno spazio vuoto significativo sarà difficile da rilevare visivamente nel markup se gli elementi della proprietà sono interspersi con il testo interno.
Spazi dei nomi XAML
Nessuno degli esempi di sintassi precedenti ha specificato uno spazio dei nomi XAML diverso dallo spazio dei nomi XAML predefinito. Nelle applicazioni WPF tipiche, lo spazio dei nomi XAML predefinito viene specificato come spazio dei nomi WPF. È possibile specificare spazi dei nomi XAML diversi dallo spazio dei nomi XAML predefinito e usare comunque una sintassi simile. Tuttavia, ovunque venga denominata una classe non accessibile all'interno dello spazio dei nomi XAML predefinito, il nome della classe deve essere preceduto dal prefisso dello spazio dei nomi XAML come mappato allo spazio dei nomi CLR corrispondente. Ad esempio, <custom:Example/>
è la sintassi dell'elemento oggetto per creare un'istanza della Example
classe, in cui lo spazio dei nomi CLR contenente tale classe (ed eventualmente le informazioni sull'assembly esterno che contiene tipi di supporto) è stato mappato in precedenza al custom
prefisso.
Per altre informazioni sugli spazi dei nomi XAML, vedi Spazi dei nomi XAML e Mapping dello spazio dei nomi per XAML WPF.
Estensioni di markup
XAML definisce un'entità di programmazione dell'estensione di markup che consente un escape dalla normale gestione del processore XAML dei valori di attributo stringa o degli elementi oggetto e rinvia l'elaborazione a una classe di backup. Il carattere che identifica un'estensione di markup a un processore XAML quando si usa la sintassi dell'attributo è la parentesi graffa di apertura ({), seguita da qualsiasi carattere diverso da una parentesi graffa di chiusura (}). La prima stringa che segue la parentesi graffa di apertura deve fare riferimento alla classe che fornisce il comportamento specifico dell'estensione, in cui il riferimento può omettere la sottostringa "Extension" se tale sottostringa fa parte del nome della classe true. Successivamente, può apparire un singolo spazio e quindi ogni carattere successivo viene usato come input dall'implementazione dell'estensione, fino a quando non viene rilevata la parentesi graffa di chiusura.
L'implementazione XAML di .NET usa la MarkupExtension classe astratta come base per tutte le estensioni di markup supportate da WPF e da altri framework o tecnologie. Le estensioni di markup implementate specificamente da WPF sono spesso destinate a fornire un mezzo per fare riferimento ad altri oggetti esistenti o per fare riferimenti posticipati agli oggetti che verranno valutati in fase di esecuzione. Ad esempio, un semplice data binding WPF viene eseguito specificando l'estensione {Binding}
di markup al posto del valore che una determinata proprietà assume in genere. Molte estensioni di markup WPF abilitano una sintassi di attributi per le proprietà in cui non sarebbe altrimenti possibile usare una sintassi di attributo. Ad esempio, un Style oggetto è un tipo relativamente complesso che contiene una serie annidata di oggetti e proprietà. Gli stili in WPF vengono in genere definiti come risorsa in un ResourceDictionaryoggetto e quindi viene fatto riferimento tramite una delle due estensioni di markup WPF che richiedono una risorsa. L'estensione di markup rinvia la valutazione del valore della proprietà a una ricerca di risorse e consente di fornire il valore della proprietà, accettando il tipo Style, nella sintassi dell'attributo Style come nell'esempio seguente:
<Button Style="{StaticResource MyStyle}">My button</Button>
In questo caso, StaticResource
identifica la StaticResourceExtension classe che fornisce l'implementazione dell'estensione di markup. La stringa MyStyle
successiva viene usata come input per il costruttore non predefinito StaticResourceExtension , in cui il parametro ottenuto dalla stringa di estensione dichiara l'oggetto richiesto ResourceKey. MyStyle
è previsto che sia il valore x:Key di un Style oggetto definito come risorsa. L'utilizzo dell'estensione di markup StaticResource richiede che la risorsa venga usata per fornire il valore della Style proprietà tramite la logica di ricerca delle risorse statiche in fase di caricamento.
Per altre informazioni sulle estensioni di markup, vedere Estensioni di markup e WPF XAML. Per informazioni di riferimento sulle estensioni di markup e altre funzionalità di programmazione XAML abilitate nell'implementazione XAML .NET generale, vedi Funzionalità del linguaggio dello spazio dei nomi XAML (x:). Per le estensioni di markup specifiche di WPF, vedi Estensioni XAML WPF.
Proprietà associate
Le proprietà associate sono un concetto di programmazione introdotto in XAML in cui le proprietà possono essere di proprietà e definite da un particolare tipo, ma impostate come attributi o elementi di proprietà in qualsiasi elemento. Lo scenario principale destinato alle proprietà associate è consentire agli elementi figlio in una struttura di markup di segnalare le informazioni a un elemento padre senza richiedere un modello a oggetti ampiamente condiviso tra tutti gli elementi. Viceversa, le proprietà associate possono essere utilizzate dagli elementi padre per segnalare informazioni agli elementi figlio. Per altre informazioni sullo scopo delle proprietà associate e su come creare proprietà associate personalizzate, vedere Panoramica delle proprietà associate.
Le proprietà associate usano una sintassi che assomiglia superficialmente alla sintassi degli elementi di proprietà, in modo da specificare anche un typeName.combinazione propertyName . Vi sono due differenze importanti:
È possibile usare typeName.combinazione propertyName anche quando si imposta una proprietà associata tramite la sintassi dell'attributo. Le proprietà associate sono l'unico caso in cui qualificare il nome della proprietà è un requisito in una sintassi di attributo.
È anche possibile usare la sintassi degli elementi di proprietà per le proprietà associate. Tuttavia, per la sintassi tipica degli elementi di proprietà, typeName specificato è l'elemento oggetto che contiene l'elemento property. Se si fa riferimento a una proprietà associata, typeName è 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 in cui gli eventi possono essere definiti da un tipo specifico, ma i gestori possono essere associati a qualsiasi elemento oggetto. Nell'implementazione WOF, spesso il tipo che definisce un evento associato è un tipo statico che definisce un servizio e talvolta tali eventi associati vengono esposti da un alias di evento indirizzato in tipi che espongono il servizio. I gestori per gli eventi associati vengono specificati tramite la sintassi degli attributi. Come per gli eventi associati, la sintassi dell'attributo viene espansa per gli eventi associati per consentire un typeName.utilizzo di eventName , dove typeName è la classe che fornisce Add
le funzioni di accesso del gestore eventi e Remove
per l'infrastruttura di eventi associata e eventName è il nome dell'evento.
Anatomia di un elemento radice XAML
La tabella seguente mostra un tipico elemento radice XAML suddiviso, che mostra gli attributi specifici di un elemento radice:
Attributo | Descrizione |
---|---|
<Page |
Apertura dell'elemento oggetto dell'elemento radice |
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
Spazio dei nomi XAML predefinito (WPF) |
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
Spazio dei nomi XAML del linguaggio XAML |
x:Class="ExampleNamespace.ExampleCode" |
Dichiarazione di classe parziale che connette markup a 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 XAML facoltativi e non consigliati
Le sezioni seguenti descrivono gli utilizzi XAML tecnicamente supportati dai processori XAML, ma che producono dettagli o altri problemi estetici che interferiscono con i file XAML che rimangono leggibili quando si sviluppano applicazioni che contengono origini XAML.
Utilizzo degli elementi proprietà facoltativi
Gli utilizzi facoltativi degli elementi di proprietà includono la scrittura esplicita delle proprietà del contenuto degli elementi che il processore XAML considera implicito. Ad esempio, quando dichiari il contenuto di un Menuoggetto , puoi scegliere di dichiarare in modo esplicito la Items raccolta di come <Menu.Items>
tag dell'elemento Menu proprietà e posizionarla in MenuItem<Menu.Items>
, anziché usare il comportamento implicito del processore XAML che tutti gli elementi figlio di un Menu oggetto devono essere e MenuItem inseriti nella Items raccolta. A volte gli utilizzi facoltativi possono contribuire a chiarire visivamente la struttura dell'oggetto come rappresentata nel markup. In alternativa, un utilizzo esplicito degli elementi di proprietà può evitare markup tecnicamente funzionale ma visivamente confuso, ad esempio le estensioni di markup annidate all'interno di un valore di attributo.
Attributi completi typeName.memberName qualificati
TypeName.Il formato memberName per un attributo funziona in modo più universale rispetto al caso dell'evento indirizzato. Ma in altre situazioni in cui la forma è superflua ed è consigliabile evitarla, se solo per motivi di stile di markup e leggibilità. Nell'esempio seguente 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>
Button.Background
funziona perché la ricerca qualificata per tale proprietà su Button ha esito positivo (Background è stata ereditata da Control) ed Button è la classe dell'elemento oggetto o di una classe di base. Control.Background
funziona perché la Control classe definisce Background effettivamente ed Control è una Button classe base.
Tuttavia, il typeName seguente.L'esempio di modulo memberName non funziona e viene quindi visualizzato come commento:
<!--<Button Label.Background="Blue">Does not work</Button> -->
Labelè un'altra classe derivata di e, se fosse stato specificato Label.Background
all'interno di Controlun Label elemento oggetto, l'utilizzo avrebbe funzionato. Tuttavia, poiché Label non è la classe o la classe base di Button, il comportamento del processore XAML specificato consiste nell'elaborare Label.Background
come proprietà associata. Label.Background
non è una proprietà associata disponibile e questo utilizzo non riesce.
elementi della proprietà baseTypeName.memberName
In modo analogo a come typeName.il modulo memberName funziona per la sintassi dell'attributo, ovvero baseTypeName.La sintassi memberName funziona per la sintassi degli elementi di proprietà. Ad esempio, la sintassi seguente funziona:
<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 della proprietà è stato assegnato come Control.Background
anche se l'elemento della proprietà era contenuto in Button
.
Ma proprio come typeName.form memberName per attributi, baseTypeName.memberName è uno stile scadente nel markup ed è consigliabile evitarlo.
Vedi anche
.NET Desktop feedback