Ausführliche Erläuterung der XAML-Syntax
In diesem Thema werden die Begriffe definiert, die verwendet werden, um die Elemente der XAML-Syntax zu beschreiben. Diese Begriffe werden häufig während des restlichen Verlaufs dieser Dokumentation verwendet, sowohl für die WPF-Dokumentation speziell als auch für die anderen Frameworks, die XAML oder die grundlegenden XAML-Konzepte verwenden, die von der XAML-Sprachunterstützung auf System.Xaml-Ebene aktiviert sind. In diesem Thema wird die grundlegende Terminologie erweitert, die im Thema XAML in WPF eingeführt wurde.
Die XAML-Sprachspezifikation
Die hier definierte XAML-Syntaxterminologie wird auch innerhalb der XAML-Sprachspezifikation definiert oder darauf verwiesen. XAML ist eine Sprache basierend auf XML und folgt oder erweitert auf XML-Strukturregeln. Einige Terminologie wird von oder basiert auf der Terminologie, die beim Beschreiben der XML-Sprache oder des XML-Dokumentobjektmodells häufig verwendet wird.
Weitere Informationen zur XAML-Sprachspezifikation finden Sie im Microsoft Download Center [MS-XAML].
XAML und CLR
XAML ist eine Markup-Sprache. Die Common Language Runtime (CLR), wie durch den Namen impliziert, ermöglicht die Laufzeitausführung. XAML ist nicht selbst eine der gängigen Sprachen, die direkt von der CLR-Laufzeit verwendet werden. Stattdessen können Sie sich XAML als Unterstützung für ein eigenes Typsystem vorstellen. Das spezielle XAML-Analysesystem, das von WPF verwendet wird, basiert auf dem CLR und dem CLR-Typsystem. XAML-Typen werden CLR-Typen zugeordnet, um eine Laufzeitdarstellung zu instanziieren, wenn der XAML-Code für WPF analysiert wird. Aus diesem Grund enthält die verbleibende Diskussion der Syntax in diesem Dokument Verweise auf das CLR-Typsystem, auch wenn die entsprechenden Syntaxdiskussionen in der XAML-Sprachspezifikation nicht. (Pro XAML-Sprachspezifikationsebene könnten XAML-Typen einem anderen Typsystem zugeordnet werden, das nicht clR sein muss, aber dies erfordert die Erstellung und Verwendung eines anderen XAML-Parsers.)
Elemente der Typen und Klassenvererbung
Als XAML-Member eines WPF-Typs verwendete Eigenschaften und Ereignisse werden oft von Basistypen geerbt. Betrachten Sie beispielsweise das folgende Beispiel: <Button Background="Blue" .../>
. Die Background-Eigenschaft ist keine sofort deklarierte Eigenschaft für die Button-Klasse, wenn Sie sich die Klassendefinition, die Spiegelungsergebnisse oder die Dokumentation ansehen wollten. Schließlich wird die Klasse Background von der Basisklasse Control geerbt.
Das Klassenvererbungsverhalten von WPF-XAML-Elementen ist eine erhebliche Ableitung von einer schemabasierten Interpretation von XML-Markups. Die Klassenvererbung kann komplex werden, insbesondere, wenn Zwischenbasisklassen abstrahiert sind oder Schnittstellen beteiligt sind. Dies ist ein Grund dafür, dass der Satz von XAML-Elementen und deren zulässigen Attribute schwierig zu darstellen ist, genau und vollständig die Schematypen zu verwenden, die normalerweise für die XML-Programmierung verwendet werden, z. B. DTD- oder XSD-Format. Ein weiterer Grund dafür ist, dass Die Erweiterbarkeits- und Typzuordnungsfeatures der XAML-Sprache selbst die Vollständigkeit einer festen Darstellung der zulässigen Typen und Member ausschließen.
Objektelementsyntax
Objektelementsyntax ist die XAML-Markupsyntax, die eine CLR-Klasse oder -Struktur instanziiert, indem sie ein XML-Element deklarieren. Diese Syntax ähnelt der Elementsyntax anderer Markupsprachen wie HTML. Die Objektelementsyntax beginnt mit einer linken Winkelklammer (<), gefolgt von dem Typnamen der Klasse oder Struktur, die instanziiert wird. Null oder mehr Leerzeichen können dem Typnamen folgen, und null oder mehr Attribute können auch für das Objektelement deklariert werden, wobei mindestens ein Leerzeichen jedes Attributname="Wert"-Paares getrennt wird. Mindestens eine der folgenden Bedingungen muss erfüllt sein:
Das Element und das Tag müssen durch einen schrägen Schrägstrich (/) geschlossen werden, gefolgt von einer rechten Winkelklammer (>).
Das öffnende Tag muss durch eine rechte Winkelklammer (>) abgeschlossen werden. Andere Objektelemente, Eigenschaftselemente oder inneren Text können dem öffnenden Tag folgen. Genau, welche Inhalte hier enthalten sein können, wird in der Regel durch das Objektmodell des Elements eingeschränkt. Das entsprechende schließende Tag für das Objektelement muss auch vorhanden sein, in ordnungsgemäßer Schachtelung und Balance mit anderen Öffnen- und Schließen-Tag-Paaren.
XAML, wie von .NET implementiert, verfügt über eine Reihe von Regeln, die Objektelemente zu Typen, Attributen in Eigenschaften oder Ereignissen und XAML-Namespaces zu CLR-Namespaces plus Assembly zuordnen. Für WPF und .NET werden XAML-Objektelemente .NET-Typen zugeordnet, wie in referenzierten Assemblys definiert, und die Attribute werden Mitgliedern 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 ist beispielsweise objektelementsyntax, die eine neue Instanz der Button-Klasse instanziiert und auch ein Attribut und einen Name-Wert für dieses Attribut angibt:
<Button Name="CheckoutButton"/>
Im folgenden Beispiel handelt es sich um objektelementsyntax, die auch XAML-Inhaltseigenschaftssyntax enthält. Der innen enthaltene Text wird verwendet, um die TextBox XAML-InhaltseigenschaftText festzulegen.
<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 nur ordnungsgemäß in einer Anwendung oder Seite, wenn es an einer erwarteten Position eines allgemeinen Inhaltsmodells oder einer Elementstruktur platziert wird. Eine MenuItem sollte beispielsweise normalerweise nur als untergeordnetes Element einer MenuBase abgeleiteten Klasse wie z. B.Menu platziert werden. Inhaltsmodelle für bestimmte Elemente werden 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 Syntaxen festgelegt. Welche Syntax für eine bestimmte Eigenschaft verwendet werden kann, hängt von den zugrunde liegenden Typsystemmerkmalen der Eigenschaft ab, die Sie festlegen.
Durch Festlegen von Eigenschaftenwerten fügen Sie Objekte wie im Laufzeitobjektdiagramm Features oder Merkmale hinzu. Der Anfängliche Zustand des erstellten Objekts aus einem Objektelement basiert auf dem Verhalten des parameterlosen Konstruktors. In der Regel verwendet Ihre Anwendung etwas anderes als eine vollständig standardmäßige Instanz eines bestimmten Objekts.
Attributsyntax (Eigenschaften)
Attributsyntax ist die XAML-Markupsyntax, die einen Wert für eine Eigenschaft festlegt, indem ein Attribut für ein vorhandenes Objektelement deklariert wird. Der Attributname muss mit dem CLR-Membernamen der Eigenschaft der Klasse übereinstimmen, die das relevante Objektelement zurückgibt. Der Attributname folgt einem Zuordnungsoperator (=). Der Attributwert muss eine Zeichenfolge sein, die in Anführungszeichen eingeschlossen ist.
Hinweis
Sie können abwechselnde Anführungszeichen verwenden, um ein literales Anführungszeichen in einem Attribut zu platzieren. Beispielsweise können Sie einzelne Anführungszeichen als Mittel verwenden, um eine Zeichenfolge zu deklarieren, die ein doppeltes Anführungszeichen enthält. Unabhängig davon, ob Sie einzelne oder doppelte Anführungszeichen verwenden, sollten Sie ein übereinstimmende Paar zum Öffnen und Schließen der Attributwertzeichenfolge verwenden. Es gibt auch Escapesequenzen oder andere Techniken zum Umgehen von Zeicheneinschränkungen, die von einer bestimmten XAML-Syntax auferlegt werden. Siehe XML-Zeichenentitäten und XAML.
Damit die Attributsyntax festgelegt werden kann, muss eine Eigenschaft öffentlich sein und schreibbar sein. Der Wert der Eigenschaft im Sicherungstypsystem muss ein Werttyp sein oder ein Verweistyp sein, der von einem XAML-Prozessor instanziiert oder referenziert werden kann, wenn auf den relevanten Sicherungstyp zugegriffen wird.
Bei WPF-XAML-Ereignissen muss das Ereignis, auf das als Attributname verwiesen wird, öffentlich sein und über einen öffentlichen Delegaten verfügen.
Die Eigenschaft oder das Ereignis muss ein Element der Klasse oder Struktur sein, die vom enthaltenden Objektelement instanziiert wird.
Verarbeitung von Attributwerten
Der Zeichenfolgenwert, der in den öffnenden und schließenden Anführungszeichen enthalten ist, wird von einem XAML-Prozessor verarbeitet. Bei Eigenschaften wird das Standardverarbeitungsverhalten durch den Typ der zugrunde liegenden CLR-Eigenschaft bestimmt.
Der Attributwert wird anhand dieser Verarbeitungsreihenfolge ausgefüllt:
Wenn der XAML-Prozessor auf eine geschweifte Klammer oder ein Objektelement trifft, das von MarkupExtension abgeleitet wird, wird die referenzierte Markuperweiterung zuerst ausgewertet, anstatt den Wert als Zeichenfolge zu verarbeiten, und das von der Markuperweiterung zurückgegebene Objekt wird als Wert verwendet. In vielen Fällen ist das von einer Markuperweiterung zurückgegebene Objekt ein Verweis auf ein vorhandenes Objekt oder ein Ausdruck, der die Auswertung bis zur Laufzeit zurücksetzt und kein neu instanziiertes Objekt ist.
Wenn die Eigenschaft mit einem TypeConverter-Attribut deklariert wird oder der Werttyp dieser Eigenschaft mit einem TypeConverter-Attribut deklariert wird, wird der Zeichenfolgenwert des Attributs als Konvertierungseingabe an den Typkonverter übermittelt, und der Konverter gibt eine neue Objektinstanz zurück.
Wenn kein TypeConverter-Wert vorhanden ist, wird versucht, eine direkte Konvertierung in den Eigenschaftentyp durchzuführen. Diese letzte Ebene ist eine direkte Konvertierung im Parser-nativen Wert zwischen XAML-Sprachgrundtypen oder eine Überprüfung auf die Namen benannter Konstanten in einer Enumeration (der Parser greift dann auf die übereinstimmenden Werte zu).
Enumerationsattributewerte
Enumerationen in XAML werden systemintern von XAML-Parsern verarbeitet, und die Member einer Enumeration sollten durch Angeben des Zeichenfolgennamens einer der benannten Konstanten der Enumeration angegeben werden.
Bei Nichtflag-Enumerationswerten besteht das systemeigene Verhalten darin, die Zeichenfolge eines Attributwerts zu verarbeiten und in einen der Enumerationswerte aufzulösen. Sie geben die Enumeration im Format Enumeration nicht an. Wert, wie beim Code. Stattdessen geben Sie nur Wert an, und die Enumeration wird vom Typ der Eigenschaft abgeleitet, die Sie festlegen. Wenn Sie ein Attribut in der Enumeration angeben. Wert- Form, es wird nicht ordnungsgemäß aufgelöst.
Bei Flagwise-Enumerationen basiert das Verhalten auf der Enum.Parse-Methode. Sie können mehrere Werte für eine Flagwise-Enumeration angeben, indem Sie jeden Wert durch ein Komma trennen. Sie können jedoch keine Enumerationswerte kombinieren, die nicht flagweise sind. Beispielsweise können Sie die Kommasyntax nicht verwenden, um zu versuchen, ein Trigger-Objekt zu erstellen, das auf mehrere Bedingungen einer Nichtflag-Enumeration wirkt:
<!--This will not compile, because Visibility is not a flagwise enumeration.-->
...
<Trigger Property="Visibility" Value="Collapsed,Hidden">
<Setter ... />
</Trigger>
...
Flagwise-Enumerationen, die Attribute unterstützen, die in XAML festgelegt sind, sind in WPF selten. Eine solche Enumeration ist jedoch StyleSimulations. Sie können z. B. die durch Trennzeichen getrennte Attributsyntax verwenden, um das Beispiel zu ändern, das in den Anmerkungen für die Glyphs-Klasse angegeben ist; StyleSimulations = "BoldSimulation"
könnte StyleSimulations = "BoldSimulation,ItalicSimulation"
werden. KeyBinding.Modifiers ist eine andere Eigenschaft, bei der mehrere Enumerationswerte angegeben werden können. Diese Eigenschaft ist jedoch ein Sonderfall, da die ModifierKeys-Enumeration den eigenen Typkonverter unterstützt. Der Typkonverter für Modifizierer verwendet ein Pluszeichen (+) als Trennzeichen anstelle eines Kommas (,). Diese Konvertierung unterstützt die traditionellere Syntax zur Darstellung von Tastenkombinationen in der Microsoft Windows-Programmierung, wie z. B. "Strg+Alt".
Eigenschaften- und Ereigniselementnamenverweise
Beim Angeben eines Attributs können Sie auf eine beliebige Eigenschaft oder ein Ereignis verweisen, das als Element des CLR-Typs vorhanden ist, den Sie für das enthaltende Objektelement instanziiert haben.
Alternativ können Sie unabhängig vom enthaltenden Objektelement auf eine angefügte Eigenschaft oder ein angefügtes Ereignis verweisen. (Angefügte Eigenschaften werden in einem bevorstehenden Abschnitt behandelt.)
Sie können auch jedes Ereignis eines beliebigen Objekts benennen, auf das über den Standard-Namespace zugegriffen werden kann, indem Sie einen teilweise qualifizierten Namen typeName. Ereignis verwenden. Diese Syntax unterstützt das Anhängen von Handlern für weitergeleitete Ereignisse, bei denen der Handler für die Behandlung von Ereignisrouting vorgesehen ist, die von untergeordneten Elementen weitergeleitet werden, aber das übergeordnete Element dieses Ereignis nicht in seiner Membertabelle hat. Diese Syntax ähnelt einer angefügten Ereignissyntax, aber das Ereignis hier ist kein true angefügtes Ereignis. Stattdessen verweisen Sie auf ein Ereignis mit einem qualifizierten Namen. Weitere Informationen finden Sie unter Übersicht über Routingereignisse.
Für einige Szenarien werden Eigenschaftsnamen manchmal als Wert eines Attributs anstelle des Attributnamens bereitgestellt. Dieser Eigenschaftsname kann auch Qualifizierer enthalten, z. B. die Eigenschaft, die im Formular ownerType.dependencyPropertyName angegeben ist. Dieses Szenario ist üblich, wenn Formatvorlagen oder Vorlagen in XAML geschrieben werden. Die Verarbeitungsregeln für Eigenschaftsnamen, die als Attributwert angegeben werden, unterscheiden sich und unterliegen dem Typ der eigenschaft, die festgelegt wird, oder durch das Verhalten bestimmter WPF-Subsysteme. Weitere Informationen finden Sie unter Styling und Vorlagenerstellung.
Eine weitere Verwendung für Eigenschaftsnamen ist, wenn ein Attributwert eine Eigenschaftseigenschaftsbeziehung beschreibt. Dieses Feature wird für die Datenbindung und für Storyboardziele verwendet und wird von der PropertyPath-Klasse und dem Typkonverter aktiviert. Eine ausführlichere Beschreibung der Lookup-Semantik finden Sie unter PropertyPath XAML-Syntax.
Eigenschaftenelement-Syntax
Eigenschaftselementsyntax ist eine Syntax, die etwas von den grundlegenden XML-Syntaxregeln für Elemente unterscheidet. In XML ist der Wert eines Attributs eine De-facto-Zeichenfolge, wobei die einzige mögliche Variante ist, welche Zeichenfolgencodierungsformat verwendet wird. In XAML können Sie anderen Objektelementen den Wert einer Eigenschaft zuweisen. Diese Funktion wird durch die Syntax des Eigenschaftselements aktiviert. Anstelle der Eigenschaft, die als Attribut innerhalb des Elementtags angegeben wird, wird die Eigenschaft mithilfe eines öffnenden Elementtags in elementTypeName.propertyName angegeben. Der Wert der Eigenschaft wird angegeben und dann wird das Eigenschaftselement geschlossen.
Insbesondere beginnt die Syntax mit einer linken Winkelklammer (<), gefolgt von dem Typnamen der Klasse oder Struktur, in der die Eigenschaftselementsyntax enthalten ist. Dies folgt sofort einem einzelnen Punkt (.), dann durch den Namen einer Eigenschaft, dann durch eine rechte Winkelklammer (>). Wie bei der Attributsyntax muss diese Eigenschaft innerhalb der deklarierten öffentlichen Member des angegebenen Typs vorhanden sein. Der Wert, der der Eigenschaft zugewiesen werden soll, ist innerhalb des Eigenschaftselements enthalten. In der Regel wird der Wert als ein oder mehrere Objektelemente angegeben, da das Angeben von Objekten als Werte das Szenario ist, in dem die Syntax des Eigenschaftselements adressiert werden soll. Schließlich muss ein äquivalenter abschließender Tag mit der gleichen Kombination aus elementTypeName.propertyName angegeben werden, und zwar in korrekter Verschachtelung und im Gleichgewicht mit anderen Element-Tags.
Im folgenden Beispiel handelt es sich um die Eigenschaftselementsyntax für die ContextMenu-Eigenschaft einer 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 Eigenschaftselements kann auch als innerer Text angegeben werden, in Fällen, in denen der angegebene Eigenschaftstyp ein Grundtyp ist, z. B. String oder eine Enumeration, in der ein Name angegeben wird. Diese beiden Verwendungen sind etwas ungewöhnlich, da jede dieser Fälle auch eine einfachere Attributsyntax verwenden könnte. Ein Szenario zum Ausfüllen eines Eigenschaftselements mit einer Zeichenfolge ist für Eigenschaften, die nicht die XAML-Inhaltseigenschaft sind, aber weiterhin für die Darstellung von UI-Text verwendet werden, und bestimmte Leerzeichenelemente, z. B. Zeilenfeeds, müssen in diesem UI-Text angezeigt werden. Die Attributsyntax kann keine Zeilenfeeds beibehalten, die Eigenschaftenelementsyntax kann jedoch aktiviert sein, solange eine bedeutende Leerraumerhaltung aktiv ist (ausführliche Informationen finden Sie unter Leerzeichenverarbeitung in XAML). Ein weiteres Szenario ist, dass die x:Uid-Anweisung auf das Eigenschaftselement angewendet werden kann und somit den Wert als Wert kennzeichnen, der in der WPF-Ausgabe-BAML oder in anderen Techniken lokalisiert werden soll.
Ein Eigenschaftselement wird in der logischen WPF-Struktur nicht dargestellt. Ein Eigenschaftselement ist nur eine bestimmte Syntax zum Festlegen einer Eigenschaft, und es handelt sich nicht um ein Element, das eine Instanz oder ein Objekt unterstützt. (Ausführliche Informationen zum logischen Strukturkonzept finden Sie unter Strukturen in WPF.)
Bei Eigenschaften, bei denen sowohl die Syntax des Attributs als auch die Eigenschaftenelementsyntax unterstützt werden, haben die beiden Syntaxen im Allgemeinen dasselbe Ergebnis, obwohl Subtilitäten wie die Behandlung von Leerzeichen geringfügig zwischen Syntaxen variieren können.
Auflistungssyntax
Die XAML-Spezifikation erfordert XAML-Prozessorimplementierungen, um Eigenschaften zu identifizieren, bei denen der Werttyp eine Auflistung ist. Die allgemeine XAML-Prozessorimplementierung in .NET basiert auf verwaltetem Code und clR und identifiziert Sammlungstypen über eine der folgenden:
Typ implementiert IList.
Typ implementiert IDictionary.
Leitet ab von Array (Weitere Informationen zu Arrays in XAML finden Sie unter x: Array-Markuperweiterung.)
Wenn der Typ einer Eigenschaft eine Auflistung ist, muss der abgeleitete Auflistungstyp im Markup nicht als Objektelement angegeben werden. Stattdessen werden die Elemente in der Auflistung als ein oder mehrere untergeordnete Elemente des Eigenschaftselements angegeben. Jedes solche Element wird beim Laden und Hinzufügen der Auflistung zu einem Objekt ausgewertet, indem die Add
-Methode der impliziten Auflistung aufgerufen wird. Beispielsweise verwendet die Eigenschaft Triggers von Style den spezialisierten Sammlungstyp TriggerCollection, der IList implementiert. Es ist nicht erforderlich, ein TriggerCollection-Objektelement im Markup zu instanziieren. Stattdessen geben Sie ein oder mehrere Trigger-Elemente als Elemente innerhalb des Style.Triggers
-Eigenschaftselements an, wobei Trigger (oder eine abgeleitete Klasse) der Typ ist, der als Elementtyp für den stark typierten und impliziten TriggerCollection-Typ 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>
Eine Eigenschaft kann sowohl ein Auflistungstyp als auch die XAML-Inhaltseigenschaft für diesen Typ und abgeleitete Typen sein, die im nächsten Abschnitt dieses Themas erläutert werden.
Ein implizites Auflistungselement erstellt ein Element in der logischen Strukturdarstellung, obwohl es nicht im Markup als Element angezeigt wird. Normalerweise führt der Konstruktor des übergeordneten Typs die Instanziierung für die Auflistung aus, die eine der Eigenschaften ist, und die anfänglich leere Auflistung wird Teil der Objektstruktur.
Hinweis
Die generischen Listen- und Wörterbuchschnittstellen (IList<T> und IDictionary<TKey,TValue>) werden für die Sammlungserkennung nicht unterstützt. Sie können die Klasse jedoch als List<T>-Basisklasse verwenden, da sie IList direkt implementiert, oder Dictionary<TKey,TValue> als Basisklasse, da sie IDictionary direkt implementiert.
Auf den .NET-Referenzseiten für Auflistungstypen wird diese Syntax mit der absichtlichen Auslassung des Objektelements für eine Auflistung gelegentlich in den XAML-Syntaxabschnitten als implizite Sammlungssyntax notiert.
Mit Ausnahme des Stammelements ist jedes Objektelement in einer XAML-Datei, die als untergeordnetes Element eines anderen Elements geschachtelt ist, wirklich ein Element, das eines oder beide der folgenden Fälle ist: ein Element 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 bevorstehenden Abschnitt erläutert). Anders ausgedrückt: Die Beziehung von übergeordneten Elementen und untergeordneten Elementen auf einer Markupseite ist wirklich ein einzelnes Objekt im Stamm, und jedes Objektelement unterhalb des Stamms ist entweder eine einzelne Instanz, die einen Eigenschaftswert des übergeordneten Elements oder eines der Elemente in einer Auflistung bereitstellt, die auch ein Auflistungseigenschaftswert des übergeordneten Elements ist. Dieses Single-Root-Konzept ist mit XML üblich und wird häufig im Verhalten von APIs verstärkt, die XAML laden, z. B. Load.
Das folgende Beispiel ist eine Syntax mit dem Objektelement für eine explizit angegebene Auflistung (GradientStopCollection).
<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. So würde beispielsweise der Versuch eines expliziten Deklarierens von TriggerCollection in dem zuvor gezeigten Triggers-Beispiel fehlschlagen. Durch explizites Deklarieren der Auflistung muss die Auflistungsklasse einen parameterlosen Konstruktor unterstützen und TriggerCollection verfügt nicht über einen parameterlosen Konstruktor.
XAML-Inhaltseigenschaften
XAML-Inhaltssyntax ist eine Syntax, die nur für Klassen aktiviert ist, die ContentPropertyAttribute als Teil ihrer Klassendeklaration angeben. Der ContentPropertyAttribute-Eigenschaftsname verweist auf die Inhaltseigenschaft für diesen Elementtyp (einschließlich abgeleiteter Klassen). Bei der Verarbeitung durch einen XAML-Prozessor werden alle untergeordneten Elemente oder inneren Text, die zwischen den öffnenden und schließenden Tags des Objektelements gefunden werden, dem Wert der XAML-Inhaltseigenschaft für dieses Objekt zugewiesen. Sie dürfen explizite Eigenschaftselemente für die Inhaltseigenschaft angeben, diese Verwendung wird jedoch in den XAML-Syntaxabschnitten in der .NET-Referenz nicht allgemein angezeigt. Die explizite/ausführliche Technik hat gelegentlichen Wert für Markupklarheit oder als Eine Frage des Markupstils, aber in der Regel besteht die Absicht einer Inhaltseigenschaft darin, das Markup zu optimieren, sodass Elemente, die intuitiv als übergeordnetes untergeordnetes Element verknüpft sind, direkt geschachtelt werden können. Eigenschaftselementtags für andere Eigenschaften eines Elements werden nicht als "Inhalt" pro strenger XAML-Sprachdefinition zugewiesen; sie werden zuvor in der Verarbeitungsreihenfolge des XAML-Parsers verarbeitet und gelten nicht als "Inhalt".
XAML-Inhaltseigenschaftswerte müssen zusammenhängend sein
Der Wert einer XAML-Inhaltseigenschaft darf nur vor oder nach allen anderen Eigenschaftenelemente für dieses Objektelement festgelegt werden. Dies gilt, ob der Wert einer XAML-Inhaltseigenschaft als Zeichenfolge oder als mindestens ein Objekt angegeben wird. Das folgende Markup wird zum Beispiel nicht geparst:
<Button>I am a
<Button.Background>Blue</Button.Background>
blue button</Button>
Dies ist im Wesentlichen unzulässig, da diese Syntax explizit mithilfe der Eigenschaftenelementsyntax für die Inhaltseigenschaft erstellt wurde, dann würde die Inhaltseigenschaft zweimal festgelegt werden:
<Button>
<Button.Content>I am a </Button.Content>
<Button.Background>Blue</Button.Background>
<Button.Content> blue button</Button.Content>
</Button>
Ein ähnlich illegales Beispiel ist, wenn es sich bei der Inhaltseigenschaft um eine Auflistung handelt, und untergeordnete Elemente werden mit Eigenschaftselementen interspersiert:
<StackPanel>
<Button>This example</Button>
<StackPanel.Resources>
<SolidColorBrush x:Key="BlueBrush" Color="Blue"/>
</StackPanel.Resources>
<Button>... is illegal XAML</Button>
</StackPanel>
Inhaltseigenschaften und Auflistungssyntax in Kombination
Um mehr als ein einzelnes Objektelement als Inhalt zu akzeptieren, muss der Typ der Inhaltseigenschaft speziell ein Auflistungstyp sein. Ähnlich wie die Eigenschaftenelementsyntax für Auflistungstypen muss ein XAML-Prozessor Typen identifizieren, die Sammlungstypen sind. Wenn ein Element über eine XAML-Inhaltseigenschaft verfügt und der Typ der XAML-Inhaltseigenschaft eine Auflistung ist, muss der implizite Auflistungstyp nicht im Markup als Objektelement angegeben werden, und die XAML-Inhaltseigenschaft muss nicht als Eigenschaftselement angegeben werden. Daher kann das scheinbare Inhaltsmodell im Markup jetzt mehr als ein untergeordnetes Element als Inhalt zugewiesen haben. Es folgt die Inhaltssyntax für eine Panel abgeleitete Klasse. Alle Panel abgeleiteten Klassen legen die XAML-Inhaltseigenschaft auf Children fest, die einen Wert vom Typ UIElementCollection erfordert.
<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>
Beachten Sie, dass weder das Eigenschaftselement für Children noch das Element für UIElementCollection im Markup erforderlich ist. Dies ist ein Designfeature von XAML, sodass rekursiv enthaltene Elemente, die eine Benutzeroberfläche definieren, intuitiver als Struktur geschachtelter Elemente mit unmittelbaren Beziehungen von übergeordneten untergeordneten Elementen dargestellt werden, ohne Eigenschaftenelementtags oder Auflistungsobjekte einzugreifen. Tatsächlich kann UIElementCollection in Markup nicht explizit als Objektelement angegeben werden. Da die einzige beabsichtigte Verwendung als implizite Auflistung gilt, macht UIElementCollection keinen öffentlichen parameterlosen Konstruktor verfügbar und kann daher nicht als Objektelement instanziiert werden.
Mischen von Eigenschaftselementen und Objektelementen in einem Objekt mit einer Content-Eigenschaft
Die XAML-Spezifikation deklariert, dass ein XAML-Prozessor erzwingen kann, dass Objektelemente, die zum Ausfüllen der XAML-Inhaltseigenschaft innerhalb eines Objektelements verwendet werden, zusammenhängend sein müssen und nicht gemischt werden dürfen. Diese Einschränkung für das Mischen von Eigenschaftselementen und Inhalten wird von den WPF-XAML-Prozessoren erzwungen.
Sie können ein untergeordnetes Objektelement als erstes direktes Markup innerhalb eines Objektelements verwenden. Anschließend können Sie Eigenschaftenelemente einführen. Oder Sie können ein oder mehrere Eigenschaftselemente angeben, dann Inhalte und dann weitere Eigenschaftselemente. Sobald jedoch ein Eigenschaftselement inhalten folgt, können Sie keine weiteren Inhalte einführen, sondern nur Eigenschaftselemente hinzufügen.
Diese Anforderung der Inhalts-/Eigenschaftselementreihenfolge gilt nicht für inneren Text, der als Inhalt verwendet wird. Es ist jedoch immer noch ein guter Markupstil, um inneren Text zusammenhängend zu halten, da ein erheblicher Leerraum schwierig ist, visuell im Markup zu erkennen, wenn Eigenschaftenelemente mit innerem Text interspersiert sind.
XAML-Namespaces
Keine der vorherigen Syntaxbeispiele hat einen anderen XAML-Namespace als den Standard-XAML-Namespace angegeben. In typischen WPF-Anwendungen wird der Standardmäßige XAML-Namespace als WPF-Namespace angegeben. Sie können andere XAML-Namespaces als den Standard-XAML-Namespace angeben und weiterhin ähnliche Syntax verwenden. Aber dann muss an einer beliebigen Stelle, an der eine Klasse benannt wird, die nicht innerhalb des Standardmäßigen XAML-Namespaces zugänglich ist, dieser Klassenname mit dem Präfix des XAML-Namespace vorangestellt werden, wie dem entsprechenden CLR-Namespace zugeordnet. Beispielsweise ist <custom:Example/>
die Syntax des Objektelements, um eine Instanz der Example
-Klasse zu instanziieren, wobei der CLR-Namensraum, der diese Klasse enthält (und möglicherweise die externen Assembly-Informationen, die Backing-Typen enthalten), zuvor auf das custom
-Präfix abgebildet wurde.
Weitere Informationen zu XML-Namespaces finden Sie unter XAML-Namespaces und Namespacezuordnung für WPF-XAML.
Markuperweiterungen
XAML definiert eine Markuperweiterungsprogrammierungsentität, die eine Escape aus der normalen XAML-Prozessorbehandlung von Zeichenfolgenattributenwerten oder Objektelementen ermöglicht und die Verarbeitung auf eine Backingklasse zurückgibt. Das Zeichen, das eine Markuperweiterung auf einen XAML-Prozessor identifiziert, wenn die Attributsyntax verwendet wird, ist die öffnende Klammer ({), gefolgt von einem anderen Zeichen als einer schließenden Klammer (}). Die erste Zeichenfolge nach der öffnenden geschweiften Klammer muss auf die Klasse verweisen, die das bestimmte Erweiterungsverhalten bereitstellt, wobei der Verweis die Unterzeichenfolge „Erweiterung“ auslassen kann, wenn diese Teilzeichenfolge Teil des „true“ Klassennamens ist. Danach kann ein einzelnes Leerzeichen angezeigt werden, und dann wird jedes erfolgreiche Zeichen als Eingabe durch die Erweiterungsimplementierung verwendet, bis die schließende Klammer gefunden wird.
Die .NET-XAML-Implementierung verwendet die abstrakte MarkupExtension-Klasse als Basis für alle von WPF unterstützten Markuperweiterungen sowie andere Frameworks oder Technologien. Die Markuperweiterungen, die WPF speziell implementiert, sollen häufig ein Mittel zum Verweisen auf andere vorhandene Objekte bereitstellen oder zurückgestellte Verweise auf Objekte vornehmen, die zur Laufzeit ausgewertet werden. Beispielsweise wird eine einfache WPF-Datenbindung durchgeführt, indem sie die {Binding}
-Markuperweiterung anstelle des Werts angibt, den eine bestimmte Eigenschaft übernehmen würde. Viele der WPF-Markuperweiterungen ermöglichen eine Attributsyntax für Eigenschaften, bei denen eine Attributsyntax nicht andernfalls möglich wäre. Beispielsweise ist ein Style-Objekt ein relativ komplexer Typ, der eine geschachtelte Reihe von Objekten und Eigenschaften enthält. Stile in WPF werden in der Regel als Ressource in einem ResourceDictionary definiert und dann über eine der beiden WPF-Markup-Erweiterungen referenziert, die eine Ressource anfordern. Die Markuperweiterung verschärft die Auswertung des Eigenschaftswerts auf eine Ressourcensuche und ermöglicht die Bereitstellung des Werts der Style-Eigenschaft, wobei der Typ in Styleder Attributsyntax wie im folgenden Beispiel angegeben wird:
<Button Style="{StaticResource MyStyle}">My button</Button>
StaticResource
identifiziert hier die Klasse, die die StaticResourceExtension-Markuperweiterungsimplementierung bereitstellt. Die nächste Zeichenfolge wird als Eingabe für den nicht standardmäßigen MyStyle
-Konstruktor verwendet, wobei der Parameter aus der Erweiterungszeichenfolge StaticResourceExtension die angeforderte ResourceKey deklariert. Von MyStyle
wird erwartet, dass der x:Key-Wert einer Style als Ressource definiert ist. Die StatischeResource-Markuperweiterung fordert die Verwendung der Ressource an, um den Eigenschaftswert über statische Style Ressourcensuchelogik zur Ladezeit bereitzustellen.
Weitere Informationen über Markuperweiterungen finden Sie unter Markuperweiterungen und WPF XAML. Eine Referenz zu Markuperweiterungen und anderen XAML-Programmierfeatures, die in der allgemeinen .NET XAML-Implementierung aktiviert sind, finden Sie unter XAML-Namespace (x:) Sprachfeatures. Für WPF-spezifische Markuperweiterungen finden Sie unter WPF XAML-Erweiterungen.
Angefügte Eigenschaften
Angefügte Eigenschaften sind ein Programmierkonzept, das in XAML eingeführt wird, wobei Eigenschaften von einem bestimmten Typ definiert werden können, aber als Attribute oder Eigenschaftselemente auf jedem Element festgelegt werden können. Das primäre Szenario, für das angefügte Eigenschaften vorgesehen sind, besteht darin, untergeordnete Elemente in einer Markupstruktur zu ermöglichen, Informationen an ein übergeordnetes Element zu melden, ohne ein umfangreiches freigegebenes Objektmodell für alle Elemente zu benötigen. Umgekehrt können angefügte Eigenschaften von übergeordneten Elementen verwendet werden, um Informationen an untergeordnete Elemente zu melden. Weitere Informationen zum Zweck angefügter Eigenschaften und zum Erstellen ihrer eigenen angefügten Eigenschaften finden Sie unter Übersicht über Angefügte Eigenschaften.
Angefügte Eigenschaften verwenden eine Syntax, die der Syntax des Eigenschaftselements ähnelt, in der Sie auch einen TypeName.propertyName-Kombination angeben. Es gibt zwei wichtige Unterschiede:
Sie können die Kombination typeName.propertyName auch verwenden, wenn Sie eine angehängte Eigenschaft über die Attributsyntax festlegen. Angefügte Eigenschaften sind der einzige Fall, in dem das Qualifizieren des Eigenschaftennamens eine Anforderung in einer Attributsyntax ist.
Sie können auch Eigenschaftenelementsyntax für angefügte Eigenschaften verwenden. Für die typische Eigenschaftselementsyntax ist der typeName, den Sie angeben, das Objektelement, das das Eigenschaftselement enthält. Wenn Sie auf eine angefügte Eigenschaft verweisen, ist der typeName die Klasse, die die angefügte Eigenschaft definiert, nicht das enthaltende Objektelement.
Angefügte Ereignisse
Angefügte Ereignisse sind ein weiteres Programmierkonzept, das in XAML eingeführt wird, in dem Ereignisse durch einen bestimmten Typ definiert werden können, aber Handler können auf jedem Objektelement angefügt werden. In der WOF-Implementierung ist häufig der Typ, der ein angefügtes Ereignis definiert, ein statischer Typ, der einen Dienst definiert, und manchmal werden diese angefügten Ereignisse von einem weitergeleiteten Ereignis alias in Typen verfügbar gemacht, die den Dienst verfügbar machen. Handler für angefügte Ereignisse werden über die Attributsyntax angegeben. Wie bei angehängten Ereignissen wird die Attributsyntax für angehängte Ereignisse erweitert, um die Verwendung von typeName.eventName zu ermöglichen, wobei typeName die Klasse ist, die die Accessoren Add
und Remove
für die Ereignishandler der angehängten Ereignisinfrastruktur bereitstellt, und eventName der Name des Ereignisses ist.
Anatomie eines XAML-Stammelements
Die folgende Tabelle zeigt ein typisches XAML-Stammelement, das die spezifischen Attribute eines Stammelements anzeigt:
attribute | BESCHREIBUNG |
---|---|
<Page |
Öffnen des Objektelements des Stammelements |
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
Der STANDARD-XAML-Namespace (WPF) |
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
Die XAML-Sprache XAML-Namespace |
x:Class="ExampleNamespace.ExampleCode" |
Die Teilklassendeklaration, die Markup mit einem codebehind-Code verbindet, der für die Teilklasse definiert ist |
> |
Ende des Objektelements für den Stamm. Das Objekt ist noch nicht geschlossen, da das Element untergeordnete Elemente enthält. |
Optionale und nichtcommendierte XAML-Verwendungen
In den folgenden Abschnitten werden XAML-Verwendungen beschrieben, die technisch von XAML-Prozessoren unterstützt werden, aber die Verbosität oder andere ästhetische Probleme erzeugen, die bei der Entwicklung von XAML-Anwendungen, die XAML-Quellen enthalten, stören.
Optionale Eigenschaftenelementverwendungen
Optionale Eigenschaftenelementverwendungen umfassen explizit das Schreiben von Elementinhaltseigenschaften, die der XAML-Prozessor implizit betrachtet. Wenn Sie beispielsweise den Inhalt von Menu deklarieren, können Sie die Items-Auflistung von Menu explizit als <Menu.Items>
-Eigenschaftselement-Tag deklarieren und jedes MenuItem-Element innerhalb von <Menu.Items>
platzieren, anstatt das implizite Verhalten des XAML-Prozessors zu verwenden, dass alle untergeordneten Elemente von MenuMenuItem sein müssen und in der Items-Auflistung platziert werden. Manchmal können die optionalen Verwendungen helfen, die Objektstruktur visuell zu klären, wie im Markup dargestellt. Oder manchmal kann eine explizite Eigenschaftselementverwendung Markup vermeiden, das technisch funktionsfähig ist, aber visuell verwirrend ist, z. B. geschachtelte Markuperweiterungen innerhalb eines Attributwerts.
VolltypName.memberName Qualifizierte Attribute
Das typeName.memberName-Formular für ein Attribut funktioniert tatsächlich universeller als nur der Routingereignisfall. Aber in anderen Situationen, in denen das Formular überflüssig ist und Sie es vermeiden sollten, wenn nur aus Gründen des Markupstils und der Lesbarkeit. Im folgenden Beispiel entsprechen jede der drei Verweise auf das Background-Attribut vollständig:
<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 Button erfolgreich ist (Background wurde vom Steuerelement geerbt) und Button ist die Klasse des Objektelements oder einer Basisklasse. Control.Background
funktioniert, da die Control-Klasse tatsächlich Background definiert, und Control eine Button-Basisklasse ist.
Das folgende Beispiel des Formulars typeName.memberName funktioniert jedoch nicht und wird daher kommentiert dargestellt:
<!--<Button Label.Background="Blue">Does not work</Button> -->
Label ist eine weitere abgeleitete Klasse von Control, und wenn Sie Label.Background
innerhalb eines Label-Objektelements angegeben hätten, hätte diese Verwendung funktioniert. Da es sich bei Label jedoch nicht um die Klasse oder Basisklasse von Buttonhandelt, verarbeitet das angegebene XAML-Prozessorverhalten Label.Background
dann als angefügte Eigenschaft. Label.Background
ist keine verfügbare angefügte Eigenschaft, und diese Verwendung schlägt fehl.
baseTypeName.memberName-Eigenschaftselemente
Ähnlich wie die Form typeName.memberName für die Syntax von Attributen funktioniert, funktioniert eine baseTypeName.memberName-Syntax für die Syntax von Eigenschaftselementen. Beispielsweise funktioniert die folgende Syntax:
<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 Eigenschaftselement als Control.Background
angegeben, obwohl das Eigenschaftselement in Button
enthalten war.
Aber genau wie die Form typeName.memberName für Attribute ist baseTypeName.memberName ein schlechter Stil im Markup, und Sie sollten ihn vermeiden.
Siehe auch
.NET Desktop feedback