Ausführliche Erläuterung der XAML-Syntax
In diesem Thema werden die Begriffe definiert, die zur Beschreibung der XAML-Syntaxelemente verwendet werden. Diese Begriffe werden häufig in den übrigen Teilen dieser Dokumentation verwendet, sowohl speziell für die WPF-Dokumentation als auch für die anderen Frameworks, die XAML oder die von der XAML-Sprachunterstützung auf der System.Xaml-Ebene aktivierten grundlegenden XAML-Konzepte verwenden. Dieses Thema baut auf der im Thema Übersicht über XAML (WPF) eingeführten grundlegenden Terminologie auf.
Dieses Thema enthält folgende Abschnitte.
- Die XAML-Sprachspezifikation
- XAML und CLR
- Objektelementsyntax
- Eigenschaften von Objektelementen
- Attributsyntax (Eigenschaften)
- Eigenschaftenelementsyntax
- Auflistungssyntax
- XAML-Inhaltseigenschaften
- Kombination von Inhaltseigenschaften und Auflistungssyntax
- XAML-Namespaces
- Markuperweiterungen
- Angefügte Eigenschaften
- Angefügte Ereignisse
- Aufbau des XAML-Stammelements
- Optionale und nicht zu empfehlende Verwendungen von XAML
- Verwandte Abschnitte
Die XAML-Sprachspezifikation
Die hier definierte Terminologie der XAML-Syntax ist auch in der XAML-Sprachspezifikation definiert, bzw. es wird darauf verwiesen. XAML basiert auf XML und folgt bzw. erweitert XML-Strukturregeln. Einige Begriffe basieren auf der Terminologie, die häufig zur Beschreibung der XML-Sprache oder des XML-Dokumentobjektmodells verwendet wird.
Um weitere Informationen über die XAML-Sprachspezifikation zu erhalten, laden Sie [MS-XAML] aus dem Microsoft Download Center herunter.
XAML und CLR
XAML ist eine Markupsprache. Die common language runtime (CLR) ermöglicht, wie vom Namen angedeutet, die Ausführung zur Laufzeit. XAML selbst ist keine der gängigen Sprachen, die von der CLR-Laufzeitumgebung verwendet werden. XAML unterstützt stattdessen das eigene Typsystem. Das bestimmte XAML-Analysesystem, das von WPF verwendet wird, basiert auf der CLR und dem CLR-Typsystem. XAML-Typen werden CLR-Typen zugeordnet, um eine Laufzeitdarstellung zu instanziieren, wenn XAML für WPF analysiert wird. Aus diesem Grund schließt die verbleibende Diskussion der Syntax in diesem Dokument Verweise auf das CLR-Typsystem ein, obwohl die entsprechenden Syntaxdiskussionen in der XAML-Sprachspezifikation keine enthält. (Gemäß der XAML-Sprachspezifikationsebene könnten XAML-Typen beliebigen anderen Typsystemen als der CLR zugeordnet werden, aber dann wäre es erforderlich, einen anderen XAML-Parser zu erstellen und zu verwenden.)
Member von Typen und Klassenvererbung
Eigenschaften und Ereignisse, die als XAML-Member eines WPF-Typs angezeigt werden, werden oft von Basistypen geerbt. Betrachten Sie z. B. das folgende Beispiel: <Button Background="Blue" .../>. Die Background-Eigenschaft ist beispielsweise keine direkt deklarierte Eigenschaft in der Button-Klasse, wenn Sie sich die Klassendefinition, Reflektionsergebnisse oder die Dokumentation anschauen. Vielmehr wird Background von der Basisklasse Control geerbt.
Das Klassenvererbungsverhalten von WPF-XAML-Elementen ist eine erhebliche Abweichung von der von einem Schema erzwungenen Interpretation des XAML-Markups. Die Klassenvererbung kann komplex werden, insbesondere, wenn es sich um abstrakte Zwischenbasisklassen handelt oder wenn Schnittstellen einbezogen sind. Dies ist ein Grund dafür, dass es schwierig ist, die XAML-Elemente und die zulässigen Attribute mit den Schematypen, die in der Regel für die XML-Programmierung verwendet werden, wie das DTD- oder das XSD-Format, angemessen und vollständig darzustellen. Ein weiterer Grund ist, dass die Erweiterungs- und Typzuordnungsfunktionen der XAML-Sprache selbst die Vollständigkeit einer festen Darstellung der zulässigen Typen und Member voraussetzen.
Objektelementsyntax
Objektelementsyntax ist die XAML-Markupsyntax, die eine CLR-Klasse oder -Struktur durch Deklarieren eines XML-Elements instanziiert. Diese Syntax ähnelt der Elementsyntax von anderen Markupsprachen wie HTML. Die Objektelementsyntax beginnt mit einer öffnenden spitzen Klammer (<) gefolgt von dem Typnamen der Klasse oder Struktur, die instanziiert wird. Dem Typnamen können 0 (null) oder mehr Leerzeichen folgen, und im Objektelement können 0 (null) oder mehr Attribute deklariert werden, wobei die einzelnen attribute name="Wert"-Paare durch ein oder mehrere Leerzeichen getrennt werden müssen. Außerdem muss eine der folgen Aussagen zutreffen:
Element und Tag müssen durch einen Schrägstrich (/) und eine unmittelbar darauf folgende schließende spitze Klammer (>) geschlossen werden.
Das Starttag muss durch eine schließende spitze Klammer (>) vervollständigt werden. Dem Starttag können andere Objektelemente, Eigenschaftenelemente oder innerer Text folgen. Welche Inhalte genau zugelassen sind, wird durch das Objektmodell des Elements festgelegt. Das entsprechende schließende Tag für das Objektelement muss ebenfalls vorhanden und richtig verschachtelt bzw. mit den anderen Tag-Paaren abgestimmt sein.
XAML in der Implementierung durch .NET enthält Regeln, mit denen Objektelemente Typen, Attribute Eigenschaften oder Ereignissen und XAML-Namespaces CLR-Namespaces plus Assembly zugeordnet werden. Für WPF und .NET Framework werden XAML-Objektelemente entsprechend den Definitionen in Assemblys, auf die verwiesen wird, Microsoft .NET-Typen und Attribute Member dieser Typen zugeordnet. Wenn Sie auf einen CLR-Typ in XAML verweisen, haben Sie auch Zugriff auf die geerbten Member dieses Typs.
Das folgende Beispiel zeigt eine Objektelementsyntax, die eine neue Instanz der Button-Klasse instanziiert sowie ein Name-Attribut und einen Wert für dieses Attribut angibt:
<Button Name="CheckoutButton"/>
Das folgende Beispiel zeigt eine Objektelementsyntax, die auch die Eigenschaftensyntax des XAML-Inhalts umfasst. Der darin enthaltene innere Text wird verwendet, um den Wert für die TextBox-XAML-Inhaltseigenschaft festzulegen, Text.
<TextBox>This is a Text Box</TextBox>
Inhaltsmodelle
Eine Klasse unterstützt möglicherweise eine Verwendung als XAML-Objektelement in Bezug auf die Syntax, aber dieses Element funktioniert in einer Anwendung oder auf einer Seite nur einwandfrei, wenn es in einer erwarteten Position eines allgemeinen Inhaltsmodells oder einer allgemeinen Elementstruktur eingefügt wird. Ein MenuItem-Element darf beispielsweise nur als untergeordnetes Element einer von MenuBase abgeleiteten Klasse, wie Menu, eingefügt werden. Inhaltsmodelle für bestimmte Elemente sind als Teil der Hinweise auf den Klassenseiten für Steuerelemente und andere WPF-Klassen dokumentiert, die als XAML-Elemente verwendet werden können.
Eigenschaften von Objektelementen
Eigenschaften in XAML werden durch eine Vielzahl möglicher Syntaxarten festgelegt. Welche Syntax für eine bestimmte Eigenschaft verwendet werden kann, hängt von den Merkmalen des zugrunde liegenden Typsystems der Eigenschaft ab, die festgelegt werden soll.
Beim Festlegen von Eigenschaftswerten fügen Sie Objekten Funktionen oder Merkmale hinzu, wie sie im Laufzeitobjektdiagramm vorhanden sind. Der Ausgangszustand des aus einem Objektelement erstellten Objekts hängt vom Verhalten des Standardkonstruktors ab. Meist verwendet die Anwendung keine ausgesprochene Standardinstanz eines angegebenen Objekts.
Attributsyntax (Eigenschaften)
Attributsyntax ist die XAML-Markupsyntax, die durch Deklarieren eines Attributs in einem vorhandenen Objektelement einen Wert für eine Eigenschaft festlegt. Der Attributname muss mit dem CLR-Membernamen der Eigenschaft der Klasse, die das relevante Objektelement unterstützt, übereinstimmen. Dem Attributnamen folgt ein Zuweisungsoperator (=). Der Attributwert muss eine in Anführungszeichen eingeschlossene Zeichenfolge sein.
Hinweis |
---|
Mithilfe von unterschiedlichen Anführungszeichen können Sie ein echtes Anführungszeichen innerhalb eines Attributs platzieren.Sie können z. B. einfache Anführungszeichen verwenden, um eine Zeichenfolge zu deklarieren, die ein doppeltes Anführungszeichen enthält.Unabhängig davon, ob Sie einfache oder doppelte Anführungszeichen verwenden, sollte zum Öffnen und Schließen der Attributwertzeichenfolge ein übereinstimmendes Paar verwendet werden.Es sind außerdem Escapesequenzen oder andere verfügbare Techniken zum Umgehen von Zeicheneinschränkungen vorhanden, die auf einer bestimmten XAML-Syntax beruhen.Siehe XML-Zeichenentitäten und XAML. |
Um mithilfe von Attributsyntax festgelegt werden zu können, muss eine Eigenschaft öffentlich sein und über Schreibzugriff verfügen. Der Wert der Eigenschaft im Unterstützungstypsystem muss ein Werttyp oder Referenztyp sein, der beim Zugriff auf den entsprechenden Unterstützungstyp instanziiert werden kann bzw. auf den ein XAML-Prozessor verweisen kann.
Für WPF-XAML-Ereignisse gilt, dass das Ereignis, auf das als Attributname verwiesen wird, öffentlich sein und einen öffentlichen Delegaten haben muss.
Die Eigenschaft/das Ereignis muss ein Member der Klasse oder Struktur sein, die von dem Container-Objektelement instanziiert wird.
Verarbeiten von Attributwerten
Der von Anführungszeichen umschlossene Zeichenfolgenwert wird von einem XAML-Prozessor verarbeitet. Für Eigenschaften wird das Standardverarbeitungsverhalten anhand des Typs der zugrunde liegenden CLR-Eigenschaft festgelegt.
Der Attributwert wird durch eine der folgenden Möglichkeiten mit Daten geladen, wobei die folgende Verarbeitungsreihenfolge gilt:
Wenn der XAML-Prozessor auf eine geschweifte Klammer oder ein von MarkupExtension abgeleitetes Objektelement trifft, wird statt der Verarbeitung des Werts als Zeichenfolge zunächst die Markuperweiterung ausgewertet, auf die verwiesen wird, und das von der Markuperweiterung zurückgegebene Objekt wird als Wert verwendet. In vielen Fällen ist das von der Markuperweiterung zurückgegebene Objekt kein neu instanziiertes Objekt, sondern ein Verweis auf ein vorhandenes Objekt oder ein Ausdruck, der die Auswertung bis zur Laufzeit zurückstellt.
Bei Deklaration der Eigenschaft mit einem attributierten TypeConverter oder bei Deklaration des Eigenschaftswerttyps mit einem attributierten TypeConverter wird der Zeichenfolgenwert des Attributs als Konvertierungseingabe an den Typkonverter übergeben, und der Konverter gibt eine neue Objektinstanz zurück.
Wenn kein TypeConverter angegeben wurde, wird versucht, eine direkte Konvertierung in den Eigenschaftentyp durchzuführen. Bei dieser letzten Ebene handelt es sich um eine direkte Konvertierung des Werts des systemeigenen Parsers zwischen Typen für XAML-Sprachprimitive oder um eine Überprüfung auf die Namen der benannten Konstanten in einer Enumeration, wobei der Parser auf die übereinstimmenden Werte zugreift.
Enumerationsattributwerte
Enumerationen in XAML werden von XAML-Parsern systemintern verarbeitet, und die Member einer Enumeration sollten durch Angabe des Zeichenfolgennamens einer der benannten Konstanten der Enumeration angegeben werden.
Bei Nicht-Flag-Enumerationen wird die Zeichenfolge eines Attributwerts verarbeitet und in einen der Enumerationswerte aufgelöst. Sie geben die Enumeration nicht im Format Enumeration.Wert an wie in Code. Stattdessen geben Sie nur Wert an, und Enumeration wird von dem Eigenschaftstyp, den Sie festlegen, abgeleitet. Wenn Sie ein Attribut im Format Enumeration.Wert angeben, kann es nicht ordnungsgemäß aufgelöst werden.
Bei Flag-Enumerationen basiert das Verhalten auf der Enum.Parse-Methode. Sie können mehrere Werte für eine Flag-Enumeration angeben, indem Sie die einzelnen Werte durch Kommas trennen. Sie können jedoch Enumerationswerte, bei denen es sich nicht um Flag-Enumerationswerte handelt, nicht kombinieren. Beispiel: Es ist nicht möglich, die Kommasyntax zu verwenden, um einen Trigger zu erstellen, der bei mehreren Bedingungen einer Nicht-Flag-Enumeration ausgeführt wird:
<!--This will not compile, because Visibility is not a flagwise enumeration.-->
...
<Trigger Property="Visibility" Value="Collapsed,Hidden">
<Setter ... />
</Trigger>
...
Flag-Enumerationen, die in XAML festlegbare Attribute unterstützen, kommen in WPF nur selten vor. Eine solche Enumeration ist StyleSimulations. Sie können die Flag-Attributsyntax mit Kommas als Trennzeichen beispielsweise verwenden, um das Beispiel in den Hinweisen zur Glyphs-Klasse zu ändern. StyleSimulations = "BoldSimulation" kann z. B. in StyleSimulations = "BoldSimulation,ItalicSimulation" geändert werden. KeyBinding.Modifiers ist eine weitere Eigenschaft, die die Angabe mehrerer Enumerationswerte zulässt. Bei dieser Eigenschaft handelt es sich jedoch um einen Spezialfall, da die ModifierKeys-Enumeration einen eigenen Typkonverter unterstützt. Der Typkonverter für Modifizierer verwendet Pluszeichen (+) statt Kommas (,) als Trennzeichen. Diese Konvertierung unterstützt die herkömmlichere Syntax zur Darstellung von Tastenkombinationen in der Microsoft Windows-Programmierung, z. B. "STRG+ALT".
Verweise auf Eigenschaften und Ereignismembernamen
Bei Angabe eines Attributs können Sie auf beliebige Eigenschaften oder Ereignisse verweisen, die als Member des CLR-Typs enthalten sind, den Sie für das Container-Objektelement instanziiert haben.
Sie können auch unabhängig vom Container-Objektelement auf eine angefügte Eigenschaft bzw. ein angefügtes Ereignis verweisen. (Angefügte Eigenschaften werden in einem späteren Abschnitt erläutert.)
Sie können auch beliebige Ereignisse beliebiger Objekte, die über den Standardnamespace zugänglich sind, mit einem teilweise qualifizierten Namen der Form Typname.Ereignis benennen. Diese Syntax unterstützt das Anfügen von Handlern für Routingereignisse, wobei der Handler zum Routing von Ereignissen untergeordneter Elemente dient, wenn das Ereignis nicht ebenfalls in der Membertabelle des übergeordneten Elements vorhanden ist. Diese Syntax ähnelt einer Syntax mit angefügten Ereignissen, tatsächlich handelt es sich jedoch nicht um ein angefügtes Ereignis. Stattdessen verweisen Sie mit einem qualifizierten Namen auf ein Ereignis. Weitere Informationen finden Sie unter Übersicht über Routingereignisse.
Bei einigen Szenarien werden Eigenschaftennamen statt als Attributname als Attributwert bereitgestellt. Diese Eigenschaftennamen können auch Qualifizierer enthalten, z. B. die im Formular ownerType.dependencyPropertyName angegebene Eigenschaft. Dieses Szenario finden Sie häufig beim Schreiben von Stilen oder Vorlagen in XAML. Für als Attributwerte bereitgestellte Eigenschaftennamen gelten andere Verarbeitungsregeln. Außerdem hängen sie vom Typ der festgelegten Eigenschaft oder vom Verhalten bestimmter WPF-Subsysteme ab. Ausführliche Informationen finden Sie unter Erstellen von Formaten und Vorlagen.
Des Weiteren finden Eigenschaftennamen Verwendung, wenn mit einem Attributwert eine Beziehung zwischen zwei Eigenschaften beschrieben wird. Diese Funktion wird für Datenbindungen und Storyboardziele verwendet und mit der PropertyPath-Klasse und dem zugehörigen Typkonverter aktiviert. Eine ausführliche Beschreibung der Suchsemantik finden Sie unter XAML-Syntax von PropertyPath.
Eigenschaftenelementsyntax
Die Eigenschaftenelementsyntax weicht zu einem gewissen Grad von den allgemeinen XML-Syntaxregeln für Elemente ab. In XML ist der Wert eines Attributs eine tatsächliche Zeichenfolge, und die einzige Variationsmöglichkeit ist die Verwendung eines anderen Codierungsformats als UTF-8. In XAML können Sie andere Objektelemente als Eigenschaftswerte zuweisen. Diese Funktion wird mit der Eigenschaftenelementsyntax aktiviert. Die Eigenschaft wird nicht innerhalb des Elementtags als Attribut, sondern mithilfe eines Startelementtags im Formular elementTypeName.propertyName angegeben. Der Wert der Eigenschaft wird angegeben, und anschließend wird das Eigenschaftenelement geschlossen.
Die Syntax beginnt mit einer öffnenden spitzen Klammer (<), auf die unmittelbar, d. h. ohne Leerzeichen, der Typname der Klasse oder Struktur folgt, die die Eigenschaftenelementsyntax enthält. Darauf folgt ohne Leerzeichen ein einzelner Punkt (.), dann der Name einer Eigenschaft und dann eine schließende spitze Klammer (>). Wie bei der Attributsyntax muss diese Eigenschaft in den deklarierten öffentliche Membern des angegebenen Typs vorhanden sein. Der Wert, der der Eigenschaft zugewiesen wird, ist im Eigenschaftenelement enthalten. In der Regel wird der Wert als mindestens ein Objektelement angegeben, da es sich bei der Angabe von Objekten als Werte um das Szenario der Eigenschaftenelementsyntax handelt. Zum Schluss muss ein entsprechendes Endtag mit derselben Elementtypname.Eigenschaftenname-Kombination bereitgestellt werden und richtig verschachtelt bzw. mit den anderen Elementtags abgestimmt sein.
Das folgende Beispiel zeigt die Eigenschaftenelementsyntax für die ContextMenu-Eigenschaft eines Button.
<Button>
<Button.ContextMenu>
<ContextMenu>
<MenuItem Header="1">First item</MenuItem>
<MenuItem Header="2">Second item</MenuItem>
</ContextMenu>
</Button.ContextMenu>
Right-click me!</Button>
Der Wert innerhalb eines Eigenschaftenelements kann auch als innerer Text angegeben werden, und zwar dann, wenn es sich bei dem angegebenen Eigenschaftentyp um einen primitiven Werttyp, z. B. String, oder eine Enumeration handelt, bei der ein Name angegeben wird. Diese beiden Verwendungsformen sind relativ selten, da in beiden Fällen auch eine einfachere Attributsyntax verwendet werden könnte. Ein Beispiel für das Auffüllen eines Eigenschaftenelements mit einer Zeichenfolge sind Eigenschaften, bei denen es sich nicht um die XAML-Inhaltseigenschaft handelt, die aber für Benutzeroberflächen-Text verwendet werden, insbesondere, wenn bestimmte Leerraumelemente wie Zeilenvorschübe in diesem Text erforderlich sind. Im Gegensatz zur Attributsyntax werden Zeilenvorschübe bei der Eigenschaftenelementsyntax beibehalten, vorausgesetzt, wenn die Beibehaltung signifikanter Leerräume aktiviert ist (ausführliche Informationen finden Sie unter Leerstellenverarbeitung in XAML). In einem anderen Szenario kann x:Uid-Direktive auf das Eigenschaftenelement angewendet werden und so den darin enthaltenen Wert als Wert markieren, der in der WPF-Ausgabe-BAML oder durch andere Techniken lokalisiert werden soll.
Ein Eigenschaftenelement wird nicht in der logischen WPF-Struktur dargestellt. Ein Eigenschaftenelement stellt lediglich eine bestimmte Syntax zur Festlegung einer Eigenschaft dar, nicht ein Element oder Objekt mit einer Instanz. (Ausführliche Informationen über das logische Strukturkonzept finden Sie unter Strukturen in WPF.)
Bei Eigenschaften, bei denen sowohl die Attribut- als auch Eigenschaftenelementsyntax unterstützt wird, ergeben beide Syntaxarten dasselbe Ergebnis, wobei sich die beiden Syntaxarten in Feinheiten, etwa im Hinblick auf den Umgang mit Leerzeichen, geringfügig unterscheiden können.
Auflistungssyntax
Die XAML-Spezifikation erfordert, dass XAML-Prozessorimplementierungen Eigenschaften identifizieren, bei deren Werttyp es sich um eine Auflistung handelt. Die allgemeine Implementierung des XAML-Prozessors in .NET basiert auf verwaltetem Code sowie der CLR, und der Prozessor identifiziert Auflistungstypen mit einer der folgenden Methoden:
Typ implementiert IList.
Typ implementiert IDictionary.
Typ wird von Array abgeleitet (weitere Informationen zu Arrays in XAML finden Sie unter x:Array-Markuperweiterung).
Wenn es sich beim Typ einer Eigenschaft um eine Auflistung handelt, muss der abgeleitete Auflistungstyp nicht im Markup als Objektelement angegeben werden. Stattdessen werden die Elemente der Auflistung als ein oder mehrere untergeordnete Elemente des Eigenschaftenelements angegeben. Die einzelnen Elemente werden beim Laden als Objekt ausgewertet und zur Auflistung hinzugefügt, indem die Add-Methode der impliziten Auflistung aufgerufen wird. Beispiel: Die Triggers-Eigenschaft von Style verwendet den speziellen Auflistungstyp TriggerCollection, der das IList-Element implementiert. Im Markup muss kein TriggerCollection-Objektelement instanziiert werden. Stattdessen geben Sie mindestens ein Trigger-Element als Elemente innerhalb des Style.Triggers-Eigenschaftenelements an, wobei Trigger (oder eine abgeleitete Klasse) als Elementtyp für die stark typisierte und implizite TriggerCollection erwartet wird.
<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>
Wie im nächsten Abschnitt dieses Themas erläutert wird, kann eine Eigenschaft sowohl ein Auflistungstyp als auch die XAML-Inhaltseigenschaft für diesen Typ und die abgeleiteten Typen sein.
Ein implizites Auflistungselement erstellt einen Member in der logischen Strukturdarstellung, auch wenn es im Markup nicht als Element erscheint. In der Regel führt der Konstruktor des übergeordneten Typs die Instanziierung für die Auflistung aus, die eine seiner Eigenschaften ist, und die zunächst leere Auflistung wird Teil der Objektstruktur.
Hinweis |
---|
Die allgemeinen Listen- und Wörterbuchschnittstellen (IList<T> und IDictionary<TKey, TValue>) werden für die Auflistungserkennung nicht unterstützt.Sie können jedoch als Basisklasse die List<T>-Klasse verwenden, da sie IList direkt implementiert, bzw. die Dictionary<TKey, TValue>-Klasse, da diese IDictionary direkt implementiert. |
Auf den .NET-Referenzseiten für Auflistungstypen wird diese Syntax mit dem absichtlichen Weglassen des Objektelements für eine Auflistung in den XAML-Syntaxbereichen gelegentlich als implizite Auflistungssyntax angegeben.
Mit Ausnahme des Stammelements ist jedes Objektelement in einer XAML-Datei, das als untergeordnetes Element eines anderen Elements geschachtelt ist, bereits ein Element, das eines oder beide der folgenden Fälle darstellt: ein Member einer impliziten Auflistungseigenschaft des übergeordneten Elements oder ein Element, das den Wert der XAML-Inhaltseigenschaft für das übergeordnete Element angibt. (XAML-Inhaltseigenschaften werden in einem späteren Abschnitt beschrieben.) Anders ausgedrückt handelt es sich bei der Beziehung von übergeordneten und untergeordneten Elementen auf einer Markupseite um ein einzelnes Objekt auf der Stammebene und bei jedem Objektelemente unter dem Stamm entweder um eine einzelne Instanz, die einen Eigenschaftswert des übergeordneten Elements bereitstellt, oder um eines der Elemente in einer Auflistung, bei der es sich ebenfalls um den Eigenschaftswert einer Auflistung des übergeordneten Elements handelt. Dieses Konzept mit einem einzelnen Stamm wird häufig mit XML verwendet und im Verhalten von APIs unterstützt, die XAML laden, z. B. Load.
Das folgende Beispiel enthält eine Syntax, wobei das Objektelement für eine Auflistung (GradientStopCollection) explizit angegeben wird.
<LinearGradientBrush>
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Offset="0.0" Color="Red" />
<GradientStop Offset="1.0" Color="Blue" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
Beachten Sie, dass es nicht immer möglich ist, die Auflistung explizit zu deklarieren. Zum Beispiel wäre es nicht möglich, das TriggerCollection-Element im zuvor angezeigten Triggers-Beispiel explizit zu deklarieren. Eine Auflistung kann nur explizit deklariert werden, wenn die Auflistungsklasse einen Standardkonstruktor unterstützt, und TriggerCollection verfügt über keinen Standardkonstruktor.
XAML-Inhaltseigenschaften
Die XAML-Inhaltssyntax wird nur bei Klassen aktiviert, die ContentPropertyAttribute als Teil der Klassendeklaration angeben. Das ContentPropertyAttribute-Element verweist auf den Eigenschaftennamen, der als Inhaltseigenschaft für den Elementtyp definiert ist (einschließlich abgeleitete Klassen). Bei der Verarbeitung mit einem XAML-Prozessor werden alle zwischen dem öffnenden und schließenden Tag des Objektelements gefundenen untergeordneten Elemente sowie innerer Text als Wert dieser XAML-Inhaltseigenschaft zugewiesen. Sie können explizite Eigenschaftenelemente für die Inhaltseigenschaft angeben, aber diese Verwendung wird im Allgemeinen in den XAML-Syntaxabschnitten im .NET-Verweis nicht angezeigt. Die explizite/verbose Methode bietet einen gelegentlichen Wert für die Markup-Klarheit oder als Markup-Stil, das Ziel einer Inhaltseigenschaft besteht jedoch in der Regel in der Strukturierung des Markups, sodass die Elemente, die intuitiv als übergeordnet-untergeordnet miteinander verbunden sind, direkt verschachtelt werden können. Eigenschaftenelementtags für andere Eigenschaften eines Elements werden nicht per strenger XAML-Sprachdefinition als "Inhalt" zugewiesen, sondern zuerst in der Verarbeitungsreihenfolge des XAML-Parsers verarbeitet und nicht als "Inhalt" eingestuft.
XAML-Inhaltseigenschaftswerte müssen zusammenhängend sein
Der Wert einer XAML-Inhaltseigenschaft muss entweder vor oder nach anderen Eigenschaftenelementen in diesem Objektelement vollständig angegeben werden. Dies gilt unabhängig davon, ob der Wert einer XAML-Inhaltseigenschaft als Zeichenfolge oder als ein oder mehrere Objekte angegeben wird. Das folgende Markup wird beispielsweise nicht analysiert:
<Button>I am a
<Button.Background>Blue</Button.Background>
blue button</Button>
Dieses Markup ist im Wesentlichen nicht zulässig, da die Inhaltseigenschaft doppelt festgelegt wird, wenn diese Syntax durch die Verwendung der Eigenschaftenelementsyntax für die Inhaltseigenschaft explizit wird:
<Button>
<Button.Content>I am a </Button.Content>
<Button.Background>Blue</Button.Background>
<Button.Content> blue button</Button.Content>
</Button>
Ein ähnliches, nicht zulässiges Beispiel für den Fall, dass es sich bei der Inhaltseigenschaft um eine Auflistung handelt und untergeordnete Elemente mit Eigenschaftenelementen vermischt werden:
<StackPanel>
<Button>This example</Button>
<StackPanel.Resources>
<SolidColorBrush x:Key="BlueBrush" Color="Blue"/>
</StackPanel.Resources>
<Button>... is illegal XAML</Button>
</StackPanel>
Kombination von Inhaltseigenschaften und Auflistungssyntax
Damit mehrere Objektelemente als Inhalt akzeptiert werden, muss der Typ der Inhaltseigenschaft ein Auflistungstyp sein. Wie auch bei Eigenschaftenelementsyntax für Auflistungstypen muss ein XAML-Prozessor Typen als Auflistungstypen identifizieren. Falls ein Element über eine XAML-Inhaltseigenschaft verfügt und der Typ der XAML-Inhaltseigenschaft eine Sammlung ist, muss der implizite Auflistungstyp im Markup nicht als Objektelement angegeben werden, und die XAML-Inhaltseigenschaft muss nicht als Eigenschaftenelement angegeben werden. In diesem Fall können dem im Markup vorhandenen Inhaltsmodell mehrere untergeordnete Elemente als Inhalt zugewiesen werden. Das folgende Beispiel zeigt die Inhaltssyntax für eine abgeleitete Panel-Klasse. Bei allen abgeleiteten Klassen von Panel wird die XAML-Inhaltseigenschaft als Children festgelegt, was einen Wert vom Typ UIElementCollection erforderlich macht.
<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>
Beachten Sie, dass weder das Eigenschaftenelement für Children noch das Element für UIElementCollection im Markup erforderlich ist. Dies ist ein Entwurfsfeature von XAML mit dem Zweck, dass rekursiv enthaltene Elemente, mit denen eine UI definiert wird, intuitiver als Struktur verschachtelter Elemente mit unmittelbaren hierarchischen Beziehungen dargestellt wird, d. h. ohne überflüssige Eigenschaftenelementtags oder Auflistungsobjekte. UIElementCollection kann im Markup nicht explizit als Objektelement angegeben werden. Da die einzige Verwendung die einer impliziten Auflistung ist, macht UIElementCollection keinen öffentlichen Standardkonstruktur verfügbar und kann aus diesem Grund nicht als Objektelement instanziiert werden.
Kombinieren von Eigenschaftenelementen und Objektelementen in einem Objekt mit einer Inhaltseigenschaft
Gemäß Deklaration in der XAML-Spezifikation kann ein XAML-Prozessor erzwingen, dass Objektelemente, die zum Laden von Daten in die XAML-Inhaltseigenschaft in einem Objektelement verwendet werden, zusammenhängend sein müssen und nicht kombiniert werden können. Diese Einschränkung zur Verhinderung der Kombination von Eigenschaftenelementen und Inhalt wird von den WPF-XAML-Prozessoren erzwungen.
Sie können ein untergeordnetes Objektelement als erstes unmittelbares Markup in einem Objektelement angeben. Dann können Sie Eigenschaftenelemente angeben. Sie können auch ein oder mehrere Eigenschaftenelemente, dann Inhalt und dann weitere Eigenschaftenelemente angeben. Nach dem Eigenschaftenelement, das dem Inhalt folgt, können Sie jedoch keinen weiteren Inhalt angeben, sondern lediglich weitere Eigenschaftenelemente.
Diese Anforderung an die Abfolge von Inhalt und Eigenschaftenelementen gilt nicht für inneren Text, der als Inhalt verwendet wird. Es ist jedoch empfehlenswert, inneren Text zusammenhängend anzugeben, da signifikante Leerzeichen im Markup schwer zu erkennen sind, wenn Eigenschaftenelemente mit innerem Text kombiniert werden.
XAML-Namespaces
In keinem der vorangehenden Syntaxbeispiele wurde ein anderer XAML-Namespace als der XAML-Standardnamespace angegeben. In typischen WPF-Anwendungen wird der XAML-Standardnamespace als WPF-Namespace angegeben. Sie können einen anderen als den XAML-Standardnamespace angeben und weiterhin eine ähnliche Syntax verwenden. Sie müssen jedoch bei jeder benannten Klasse, die im XAML-Standardnamespace nicht verfügbar ist, dem Klassennamen das Präfix des XAML-Namespace voranstellen, das für die Zuordnung des entsprechenden CLR-Namespace verwendet wurde. Beispiel: <custom:Example/> dient als Objektelementsyntax zur Instanziierung einer Instanz der Example-Klasse, wobei der CLR-Namespace, der die Klasse enthält (und möglicherweise auch die externen Assemblyinformationen, die Unterstützungstypen enthalten), zuvor dem custom-Präfix zugeordnet wurde.
Weitere Informationen zu XAML-Namespaces finden Sie unter XAML-Namespaces und Namespacezuordnung für WPF-XAML.
Markuperweiterungen
XAML definiert eine Programmierentität für Markuperweiterungen, mit der die reguläre Handhabung von Zeichenfolgen-Attributwerten und Objektelementen durch den XAML-Prozessor ergänzt werden kann, wobei die Verarbeitung in eine Sicherungsklasse zurückgestellt wird. Zur Kennzeichnung der Markuperweiterung für den XAML-Prozessor bei Verwendung von Attributsyntax wird die öffnende geschweifte Klammer ({) verwendet, gefolgt von einem beliebigen anderen Zeichen mit Ausnahme der schließenden geschweiften Klammer (}). Die erste Zeichenfolge nach der öffnenden geschweiften Klammer muss auf die Klasse verweisen, die das spezifische Erweiterungsverhalten bereitstellt, wobei die Teilzeichenfolge "Extension" im Verweis weggelassen werden kann, wenn diese Teilzeichenfolge Teil des eigentlichen Klassennamens ist. Darauf kann ein einzelnes Leerzeichen folgen. Die darauf folgenden Zeichen bis zur schließenden geschweiften Klammer werden von der Erweiterungsimplementierung als Eingabe verwendet.
Die .NET XAML-Implementierung verwendet die abstrakte MarkupExtension-Klasse als Basis für alle von WPF sowie anderen Frameworks oder Technologien unterstützten Markuperweiterungen. Die von WPF speziell implementierten Markuperweiterungen dienen häufig dazu, eine Möglichkeit bereitzustellen, bei der Verwendung von Attributsyntax auf andere vorhandene Objekte zu verweisen oder zurückgestellte Verweise auf Objekte auszuführen, die zur Laufzeit ausgewertet werden. Beispiel: Für eine einfache WPF-Datenbindung geben Sie statt des Werts, der normalerweise von einer bestimmten Eigenschaft verwendet wird, die Markuperweiterung {Binding} an. Viele der WPF-Markuperweiterungen ermöglichen die Verwendung einer Attributsyntax für Eigenschaften, was andernfalls nicht möglich wäre. Beispiel: Ein Style-Objekt ist ein relativ komplexer Typ, der eine geschachtelte Reihe von Objekten und Eigenschaften enthält. Stile in WPF werden in der Regel als Ressourcen in einem ResourceDictionary definiert, und dann wird mit einer der beiden WPF-Markuperweiterungen, die eine Ressource anfordern, darauf verwiesen. Die Markuperweiterung stellt die Auswertung des Eigenschaftswerts in eine Ressourcensuche zurück und ermöglicht die Bereitstellung der Style-Eigenschaft, wobei der Typ Style verwendet wird, in Attributsyntax wie im folgenden Beispiel:
<Button Style="{StaticResource MyStyle}">My button</Button>
Hier identifiziert StaticResource die StaticResourceExtension-Klasse, die die Markuperweiterungsimplementierung bereitstellt. Die nächste Zeichenfolge MyStyle wird als Eingabe für den nicht standardmäßigen StaticResourceExtension-Konstruktor verwendet, wobei der angeforderte ResourceKey durch den Parameter aus der Erweiterungszeichenfolge deklariert wird. MyStyle wird als x:Key-Wert eines Style-Elements erwartet, das als Ressource definiert ist. Die Verwendung von StaticResource-Markuperweiterung erfordert, dass die Ressource verwendet wird, um den Style-Eigenschaftswert über die Logik einer statische Ressourcensuche zum Ladezeitpunkt bereitzustellen.
Weitere Informationen über Markuperweiterungen finden Sie unter Markuperweiterungen und WPF-XAML. Referenzen zu Markuperweiterungen und anderen in der allgemeinen .NET XAML-Implementierung aktivierten XAML-Programmierfunktionen finden Sie unter Sprachfeatures des XAML-Namespace (x:). WPF-spezifische Markuperweiterungen finden Sie unter WPF-XAML-Erweiterungen.
Angefügte Eigenschaften
Angefügte Eigenschaften sind ein in XAML eingeführtes Programmierkonzept, in dem ein bestimmter Typ Eigenschaften besitzen und definieren kann, diese aber als Attribute oder Eigenschaftenelemente für jedes Element festgelegt werden können. Das primäre Szenario für angefügte Eigenschaften ist die Aktivierung von untergeordneten Elementen in einer Markupstruktur, um Informationen an ein übergeordnetes Element zu übermitteln, ohne dass ein umfassendes gemeinsam genutztes Objektmodell über alle Elemente hinweg erforderlich ist. Umgekehrt können angefügte Eigenschaften von übergeordneten Elementen verwendet werden, um Informationen an untergeordnete Elemente zu übermitteln. Weitere Informationen zu angefügten Eigenschaften und dazu, wie Sie eigene angefügte Eigenschaften erstellen, finden Sie unter Übersicht über angefügte Eigenschaften.
Die für angefügte Eigenschaften verwendete Syntax ähnelt der Eigenschaftenelementsyntax insofern, dass ebenfalls eine Typname.Eigenschaftenname-Kombination angegeben wird. Es gibt jedoch zwei wichtige Unterschiede:
Sie können die Typname.Eigenschaftenname-Kombination auch dann verwenden, wenn Sie eine angefügte Eigenschaft mittels Attributsyntax festlegen. Angefügte Eigenschaften sind der einzige Fall, bei dem der Eigenschaftenname in der Attributsyntax qualifiziert werden muss.
Sie können auch Eigenschaftenelementsyntax für angefügte Eigenschaften verwenden. Typischerweise ist der in der Eigenschaftenelementsyntax angegebene Typname jedoch das Objektelement, in dem das Eigenschaftenelement enthalten ist. Wenn Sie auf eine angefügte Eigenschaft verweisen, ist der Typname die Klasse, die die angefügte Eigenschaft definiert, nicht das Container-Objektelement.
Angefügte Ereignisse
Bei angefügten Ereignissen handelt es sich um ein weiteres in XAML eingeführtes Programmierungskonzept mit dem Zweck, dass Ereignisse mit einem bestimmten Typ definiert werden, Handler jedoch an beliebige Objektelemente angefügt werden können. In der WPF-Implementierung handelt es sich bei dem Typ, mit dem ein angefügtes Ereignis definiert wird, oft um einen statischen Typ, der einen Dienst definiert, und in einigen Fällen werden diese angefügten Ereignisse über einen Routingereignisalias in Typen verfügbar gemacht, die den Dienst verfügbar machen. Handler für angefügte Ereignisse werden mit Attributsyntax angegeben. Die Attributsyntax wird für angefügte Ereignisse ebenfalls erweitert, um die Verwendung einer Typname.Ereignisname-Kombination zu ermöglichen, wobei Typname die Klasse ist, die Add- und Remove-Ereignishandleraccessoren für die angefügte Ereignisinfrastruktur bereitstellt, und Ereignisname der Ereignisname ist.
Aufbau des XAML-Stammelements
In der folgenden Tabelle ist der Aufbau eines typischen XAML-Stammelements mit den spezifischen Attributen eines Stammelements dargestellt:
<Page |
Öffnendes Objektelement des Stammelements |
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" |
Der XAML-Standardnamespace (WPF) |
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" |
Der XAML-Sprachnamespace |
x:Class="ExampleNamespace.ExampleCode" |
Die Deklaration der partiellen Klasse, die das Markup mit einem für die partielle Klasse definierten Code-Behind verbindet |
> |
Ende des Objektelements für den Stamm. Das Objekt ist noch nicht geschlossen, da das Element untergeordnete Elemente enthält. |
Optionale und nicht zu empfehlende Verwendungen von XAML
In den folgenden Abschnitten werden XAML-Verwendungen beschrieben, die technisch von XAML-Prozessoren unterstützt werden, jedoch Ausführlichkeitsgrad- oder andere ästhetische Probleme erzeugen, die die Lesbarkeit von XAML-Dateien beeinträchtigen, wenn Sie Anwendungen mit XAML-Quellen entwickeln.
Optionale Verwendungen von Eigenschaftenelementen
Zu den optionalen Verwendungen von Eigenschaftenelementen gehört das explizite Schreiben von Elementinhaltseigenschaften, die vom XAML-Prozessor als implizit behandelt werden. Beispiel: Wenn Sie den Inhalt eines Menu deklarieren, können Sie die Items-Auflistung des Menu explizit als ein <Menu.Items>-Eigenschaftenelementtag deklarieren und jedes MenuItem in <Menu.Items> platzieren, statt das implizite XAML-Prozessorverhalten zu verwenden, bei dem jedes untergeordnete Element eines Menu ein MenuItem sein muss, die alle in die Items-Auflistung eingefügt werden. In einigen Fällen kann mit den optionalen Verwendungsmöglichkeiten die Objektstruktur im Markup verständlicher dargestellt werden. Oder Sie können durch ein explizit angegebenes Eigenschaftenelement Markup vermeiden, das technisch seinen Zweck erfüllt, dessen Darstellung jedoch eher verwirrend ist, wie z. B. verschachtelte Markuperweiterungen in einem Attributwert.
Voll qualifizierte Attribute (Typname.Membername)
Die Form Typname.Membername für Attribute kann universeller verwendet werden als nur bei Routingereignissen. In anderen Situationen ist diese Form jedoch überflüssig, und Sie sollten sie zugunsten eines besseren Markupformats und besserer Lesbarkeit vermeiden. Die drei Verweise auf das Background-Attribut im folgenden Beispiel sind vollständig äquivalent:
<Button Background="Blue">Background</Button>
<Button Button.Background="Blue">Button.Background</Button>
<Button Control.Background="Blue">Control.Background</Button>
Button.Background funktioniert, da die qualifizierte Suche für diese Eigenschaft nach Button erfolgreich ist (Background wurde vom Steuerelement geerbt) und Button die Klasse des Objektelements oder eine Basisklasse ist. Control.Background funktioniert, da die Control-Klasse Background definiert und Control eine Button -Basisklasse ist.
Das folgende Beispiel mit der Form Typname.Membername funktioniert jedoch nicht und wird kommentiert:
<!--<Button Label.Background="Blue">Does not work</Button> -->
Label ist eine weitere abgeleitete Klasse von Control. Wenn Sie Label.Background in einem Label-Objektelement angegeben hätten, hätte diese Methode funktioniert. Da Label jedoch nicht die Klasse oder Basisklasse von Button ist, verarbeitet der XAML-Prozessor Label.Background dann als angefügte Eigenschaft. Da es sich bei Label.Background nicht um eine verfügbare angefügte Eigenschaft handelt, schlägt diese Methode fehl.
Basistypname.Membername-Eigenschaftenelemente
So wie die Form Typname.Membername für Attributsyntax funktioniert, kann die Form Basistypname.Membername für Eigenschaftenelementsyntax verwendet werden. Beispiel:
<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>
Hier wurde das Eigenschaftenelement als Control.Background angegeben, obwohl das Eigenschaftenelement in Button enthalten war.
Wie die Form Typname.Membername bei Attributen ist aber auch die Form Basistypname.Membername kein gutes Markupformat und sollte nicht verwendet werden.
Siehe auch
Konzepte
Übersicht über Abhängigkeitseigenschaften
XAML- und benutzerdefinierte Klassen für WPF