Ausführliche Erläuterung der XAML-Syntax

In diesem Thema werden die Begriffe definiert, mit denen die Elemente der XAML-Syntax beschrieben werden. Diese Begriffe werden im weiteren Verlauf dieser Dokumentation häufig verwendet, sowohl für die WPF-Dokumentation speziell als auch für die anderen Frameworks, die XAML verwenden, oder für die grundlegenden XAML-Konzepte, die von der XAML-Sprachunterstützung auf System.Xaml-Ebene aktiviert werden. Dieses Thema baut auf der grundlegenden Terminologie auf, die im Thema XAML in WPF eingeführt wurde.

In diesem Thema werden die Begriffe definiert, mit denen die Elemente der XAML-Syntax beschrieben werden. Diese Begriffe werden im weiteren Verlauf dieser Dokumentation häufig verwendet, sowohl für die WPF-Dokumentation speziell als auch für die anderen Frameworks, die XAML verwenden, oder für die grundlegenden XAML-Konzepte, die von der XAML-Sprachunterstützung auf System.Xaml-Ebene aktiviert werden. Dieses Thema baut auf der grundlegenden Terminologie auf, die im Thema XAML-Übersicht (WPF) eingeführt wurde.

Die XAML-Sprachspezifikation

Die hier definierte XAML-Syntaxterminologie wird auch in der XAML-Sprachspezifikation definiert oder referenziert. XAML ist eine Sprache, die auf XML basiert und XML-Strukturregeln folgt oder erweitert. Ein Teil der Terminologie wird von oder basiert auf der Terminologie, die häufig bei der Beschreibung der XML-Sprache oder des XML-Dokumentobjektmodells verwendet wird.

Weitere Informationen zur XAML-Sprachspezifikation finden Sie unter [MS-XAML] aus dem Microsoft Download Center.

XAML und CLR

XAML ist eine Markupsprache. Die Common Language Runtime (CLR), wie durch ihren Namen impliziert, ermöglicht die Laufzeitausführung. XAML ist allein keine der gängigen Sprachen, die direkt von der CLR-Runtime verwendet werden. Stattdessen können Sie sich XAML als Unterstützung für ein eigenes Typsystem denken. Das spezielle 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 enthält der Rest der Syntaxdiskussion in diesem Dokument Verweise auf das CLR-Typsystem, obwohl dies bei den entsprechenden Syntaxdiskussionen in der XAML-Sprachspezifikation nicht der Fall ist. (Pro XAML-Sprachspezifikationsebene können XAML-Typen jedem anderen Typsystem zugeordnet werden, das nicht die CLR sein muss, aber dies erfordert die Erstellung und Verwendung eines anderen XAML-Parsers.)

Member von Typen und Klassenvererbung

Eigenschaften und Ereignisse, die als XAML-Member eines WPF-Typs angezeigt werden, werden häufig von Basistypen geerbt. Betrachten Sie beispielsweise dieses Beispiel: <Button Background="Blue" .../> . Die -Eigenschaft ist keine sofort deklarierte Eigenschaft für die Klasse, wenn Sie die Klassendefinition, Reflektionsergebnisse oder BackgroundButton die Dokumentation betrachten würden. Stattdessen wird Background von der Basisklasse Control geerbt.

Das Klassenvererbungsverhalten von WPF-XAML-Elementen ist eine erhebliche Abweichung von einer schemabasierten Interpretation von XML-Markup. Die Klassenvererbung kann komplex werden, insbesondere wenn Zwischenbasisklassen abstrakt sind oder Schnittstellen beteiligt sind. Dies ist ein Grund dafür, dass der Satz von XAML-Elementen und deren zulässigen Attributen unter Verwendung der Schematypen, die normalerweise für die XML-Programmierung verwendet werden, wie z. B. DTD- oder XSD-Format, schwer genau und vollständig darzu stellen ist. Ein weiterer Grund ist, dass Erweiterbarkeits- und Typzuordnungsfeatures der XAML-Sprache selbst die Vollständigkeit jeder festen Darstellung der zulässigen Typen und Member ausschließen.

Objektelementsyntax

Objektelementsyntax ist die XAML-Markupsyntax, die eine CLR-Klasse oder -Struktur instanziiert, indem ein XML-Element deklariert wird. Diese Syntax ähnelt der Elementsyntax anderer Markupsprachen wie HTML. Die Objektelementsyntax beginnt mit einer linken spitzen Klammer ( ), unmittelbar gefolgt vom 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, und ein oder mehrere Leerzeichen trennen jedes Attributname="Wert"-Paar. Schließlich muss eine der folgenden Bedingungen erfüllt sein:

  • Das Element und das Tag müssen durch einen Schrägstrich (/) geschlossen werden, unmittelbar gefolgt von einer rechten eckigen Klammer ( > ).

  • Das öffnende Tag muss durch eine rechte eckige Klammer () abgeschlossen > werden. Andere Objektelemente, Eigenschaftselemente oder innerer Text können dem öffnenden Tag folgen. Genau der Inhalt, der hier enthalten sein kann, wird in der Regel durch das Objektmodell des Elements eingeschränkt. Das entsprechende schließende Tag für das Objektelement muss ebenfalls vorhanden sein, in der richtigen Schachtelung und im Gleichgewicht mit anderen öffnenden und schließenden Tagpaaren.

XAML, wie von .NET implementiert, verfügt über eine Reihe von Regeln, die Objektelemente Typen, Attributen Eigenschaften oder Ereignissen und XAML-Namespaces CLR-Namespaces plus Assembly zuordnen. Für WPF und .NET werden XAML-Objektelemente .NET-Typen wie in Referenzassemblys definiert, und die Attribute werden Membern dieser Typen zuordnen. Wenn Sie in XAML auf einen CLR-Typ verweisen, haben Sie auch Zugriff auf die geerbten Member dieses Typs.

Im folgenden Beispiel wird beispielsweise die Objektelementsyntax verwendet, die eine neue Instanz der -Klasse instanziiert und außerdem ein Attribut und einen Wert ButtonName für dieses Attribut angibt:

<Button Name="CheckoutButton"/>

Im folgenden Beispiel wird die Objektelementsyntax verwendet, die auch xaml-Inhaltseigenschaftssyntax enthält. Der in enthaltene innere Text wird verwendet, um die TextBox XAML-Inhaltseigenschaft Text 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. Beispielsweise sollte ein in der Regel nur als untergeordnetes -Klasse einer abgeleiteten MenuItem Klasse wie MenuBase platziert Menu 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.

Indem Sie Werte von Eigenschaften festlegen, fügen Sie Objekten Features oder Merkmale hinzu, wie sie im Laufzeitobjektdiagramm vorhanden sind. Der Anfangszustand des erstellten Objekts aus einem Objektelement basiert auf dem parameterlosen Konstruktorverhalten. 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 durch Deklarieren eines Attributs für ein vorhandenes Objektelement legt. Der Attributname muss mit dem CLR-Membernamen der Eigenschaft der Klasse übereinstimmen, die das relevante Objektelement sichern soll. Auf den Attributnamen folgt ein Zuweisungsoperator (=). 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 innerhalb eines Attributs zu platzieren. Beispielsweise können Sie einfache Anführungszeichen als Mittel verwenden, um eine Zeichenfolge zu deklarieren, die ein doppeltes Anführungszeichen enthält. Unabhängig davon, ob Sie einfache oder doppelte Anführungszeichen verwenden, sollten Sie ein übereinstimmende Paar verwenden, um die Attributwertzeichenfolge zu öffnen und zu schließen. Es gibt auch Escapesequenzen oder andere Techniken zum Umgehen von Zeicheneinschränkungen, die von einer bestimmten XAML-Syntax festgelegt werden. Weitere Informationen finden Sie unter XML-Zeichenentitäten und XAML.

Um über die Attributsyntax festgelegt zu werden, muss eine Eigenschaft öffentlich und schreibbar sein. Der Wert der -Eigenschaft im Backing Type-System muss ein Werttyp oder ein Verweistyp sein, der von einem XAML-Prozessor instanziiert oder referenziert werden kann, wenn auf den relevanten Hintergrundtyp verwiesen 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 Member der Klasse oder Struktur sein, die bzw. die vom enthaltenden Objektelement instanziiert wird.

Verarbeiten von Attributwerten

Der in den öffnenden und schließenden Anführungszeichen enthaltene Zeichenfolgenwert wird von einem XAML-Prozessor verarbeitet. Für Eigenschaften wird das Standardverarbeitungsverhalten durch den Typ der zugrunde liegenden CLR-Eigenschaft bestimmt.

Der Attributwert wird mithilfe dieser Verarbeitungs reihenfolge durch eine der folgenden Werte gefüllt:

  1. Wenn der XAML-Prozessor auf eine geschweifte Klammer oder ein objektorientiertes Element trifft, das von ableitungt, wird zuerst die Markuperweiterung ausgewertet, auf die verwiesen wird, anstatt den Wert als Zeichenfolge zu verarbeiten, und das von der Markuperweiterung zurückgegebene Objekt wird als Wert MarkupExtension 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ücklädt und kein neu instanziiertes Objekt ist.

  2. Wenn die -Eigenschaft mit einem attribut erstellten deklariert wird oder der Werttyp dieser Eigenschaft mit einem Attribut deklariert wird, wird der Zeichenfolgenwert des Attributs als Konvertierungseingabe an den Typkonverter übermittelt, und der Konverter gibt eine neue Objektinstanz TypeConverterTypeConverter zurück.

  3. Wenn kein -Objekt vor TypeConverter liegt, wird eine direkte Konvertierung in den Eigenschaftentyp versucht. Diese letzte Ebene ist eine direkte Konvertierung auf dem nativen Parserwert zwischen primitiven XAML-Sprachtypen oder eine Überprüfung auf die Namen benannter Konstanten in einer Enumeration (der Parser greifen dann auf die übereinstimmenden Werte zu).

Enumerationsattributwerte

Enumerationen in XAML werden intrinsisch von XAML-Parsern verarbeitet, und die Member einer Enumeration sollten durch Angabe des Zeichenfolgennamens einer der benannten Konstanten der Enumeration angegeben werden.

Bei Nichtflag-Enumerationswerten besteht das native Verhalten in der Verarbeitung der Zeichenfolge eines Attributwerts und deren Auflösung in einen der Enumerationswerte. Sie geben die Enumeration nicht im Format Enumeration an.Wertwie im Code. Stattdessen geben Sie nur Valuean, und Enumeration wird durch den Typ der Eigenschaft abgeleitet, die Sie festlegen. Wenn Sie ein Attribut in der Enumeration angeben.Wertform, wird nicht ordnungsgemäß behoben.

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. Enumerationswerte, die nicht flagwise sind, können jedoch nicht kombiniert werden. Beispielsweise können Sie die Kommasyntax nicht verwenden, um zu versuchen, eine zu erstellen, die für mehrere Bedingungen einer Trigger Nichtflagenumeration fungiert:

<!--This will not compile, because Visibility is not a flagwise enumeration.-->  
...  
<Trigger Property="Visibility" Value="Collapsed,Hidden">  
  <Setter ... />  
</Trigger>  
...  

Flagweise Enumerationen, die Attribute unterstützen, die in XAML festgelegt werden können, sind in WPF selten. Eine solche Enumeration ist jedoch StyleSimulations . Sie können z. B. die durch Trennzeichen getrennte flagwise-Attributsyntax verwenden, um das in den Hinweise für die Klasse bereitgestellte Beispiel zu ändern. Könnte zu GlyphsStyleSimulations = "BoldSimulation"StyleSimulations = "BoldSimulation,ItalicSimulation" werden. KeyBinding.Modifiers ist eine weitere Eigenschaft, bei der mehr als ein Enumerationswert angegeben werden kann. Diese Eigenschaft ist jedoch ein Sonderfall, da die ModifierKeys -Enumeration ihren eigenen Typkonverter unterstützt. Der Typkonverter für Modifizierer verwendet ein Pluszeichen (+) als Trennzeichen anstelle eines Kommas (,). Diese Konvertierung unterstützt die herkömmlichere Syntax, um Tastenkombinationen in der Microsoft Windows darstellen, z. B. "STRG+ALT".

Eigenschaften und Verweise auf Ereignismembernamen

Wenn Sie ein Attribut angeben, können Sie auf jede Eigenschaft oder jedes Ereignis verweisen, die bzw. das als Member 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 zukünftigen Abschnitt erläutert.)

Sie können auch jedes Ereignis aus jedem Objekt benennen, auf das über den Standardnamespace zugegriffen werden kann, indem Sie typeName verwenden.teilweise qualifizierter Name des Ereignisses; Diese Syntax unterstützt das Anfügen von Handlern für Routingereignisse, bei denen der Handler das Ereignisrouting von untergeordneten Elementen verarbeiten soll, aber das übergeordnete Element nicht auch dieses Ereignis in seiner Members-Tabelle enthält. Diese Syntax ähnelt einer angefügten Ereignissyntax, aber das Ereignis hier ist kein true attached-Ereignis. Stattdessen verweisen Sie auf ein Ereignis mit einem qualifizierten Namen. Weitere Informationen finden Sie unter Übersicht über Routingereignisse.

In einigen Szenarien werden Eigenschaftsnamen manchmal als Wert eines Attributs und nicht als Attributname bereitgestellt. Dieser Eigenschaftenname kann auch Qualifizierer enthalten, z. B. die im Format ownerTypeangegebene Eigenschaft. dependencyPropertyName. Dieses Szenario tritt häufig auf, wenn Stile oder Vorlagen in XAML geschrieben werden. Die Verarbeitungsregeln für Eigenschaftsnamen, die als Attributwert bereitgestellt werden, unterscheiden sich und werden durch den Typ der festzulegenden Eigenschaft oder das Verhalten bestimmter WPF-Subsysteme gesteuert. Weitere Informationen finden Sie unter Formatieren und Vorlagen.

Eine weitere Verwendung für Eigenschaftennamen ist, wenn ein Attributwert eine Eigenschaft-Eigenschaft-Beziehung beschreibt. Dieses Feature wird für die Datenbindung und für Storyboardziele verwendet und von der PropertyPath -Klasse und ihrem Typkonverter aktiviert. Eine ausführlichere Beschreibung der Suchsemantik finden Sie unter PropertyPath-XAML-Syntax.

Eigenschaftenelement-Syntax

Die Syntax von Eigenschaftselementen ist eine Syntax, die von den grundlegenden XML-Syntaxregeln für Elemente abweicht. In XML ist der Wert eines Attributs eine de-facto-Zeichenfolge, wobei die einzige mögliche Variation darin besteht, welches Zeichenfolgencodierungsformat verwendet wird. In XAML können Sie anderen Objektelementen den Wert einer Eigenschaft zuweisen. Diese Funktion wird durch die Syntax des Eigenschaftselements aktiviert. Anstatt die Eigenschaft als Attribut innerhalb des Elementtags anzugeben, wird die Eigenschaft mithilfe eines öffnenden Elementtags in elementTypeNameangegeben. propertyName-Formular, der Wert der Eigenschaft wird in angegeben, und dann wird das Eigenschaftselement geschlossen.

Insbesondere beginnt die Syntax mit einer linken spitzen Klammer ( < ), gefolgt sofort vom Typnamen der Klasse oder Struktur, in der die Syntax des Eigenschaftselements enthalten ist. Darauf folgt sofort ein einzelner Punkt (.), dann der Name einer Eigenschaft und dann eine rechte spitze Klammer ( > ). Wie bei der Attributsyntax muss diese Eigenschaft in den deklarierten öffentlichen Membern des angegebenen Typs vorhanden sein. Der Wert, der der Eigenschaft zugewiesen werden soll, ist im Eigenschaftenelement enthalten. In der Regel wird der Wert als ein oder mehrere Objektelemente angegeben, da die Angabe von Objekten als Werte das Szenario ist, in dem die Syntax des Eigenschaftenelements adressiert werden soll. Schließlich ein entsprechendes schließendes Tag, das den gleichen elementTypeNameangibt. Die Kombination von propertyName muss in der richtigen Schachtelung bereitgestellt werden und mit anderen Elementtags ausgeglichen werden.

Im Folgenden ist beispielsweise die Syntax des Eigenschaftenelements für die ContextMenu -Eigenschaft eines Button angegeben.

<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, wenn der angegebene Eigenschaftentyp ein primitiver Werttyp ist, z. B. oder eine Enumeration, bei der String ein Name angegeben wird. Diese beiden Verwendungen sind etwas ungewöhnlich, da jeder dieser Fälle auch eine einfachere Attributsyntax verwenden kann. Ein Szenario zum Auffüllen eines Eigenschaftselements mit einer Zeichenfolge ist für Eigenschaften, die nicht die XAML-Inhaltseigenschaft sind, aber weiterhin für die Darstellung von Benutzeroberflächentext verwendet werden, und bestimmte Leerraumelemente wie Zeilenfeeds müssen in diesem Benutzeroberflächentext angezeigt werden. Die Attributsyntax kann keine Linefeeds beibehalten, aber die Syntax von Eigenschaftselementen kann verwendet werden, solange eine signifikante Beibehaltung des Leerraums aktiv ist (weitere Informationen finden Sie unter Leerraumverarbeitung in XAML). Ein weiteres Szenario ist, dass die x:Uid-Direktive auf das Eigenschaftselement angewendet werden kann und daher den Wert in als Wert markieren kann, der in der WPF-Ausgabe-BAML oder durch andere Techniken lokalisiert werden soll.

Ein Eigenschaftenelement wird in der logischen WPF-Struktur nicht dargestellt. Ein Eigenschaftenelement ist nur eine bestimmte Syntax zum Festlegen einer Eigenschaft und kein Element, das eine Instanz oder ein Objekt unterstützt. (Ausführliche Informationen zum Konzept der logischen Struktur finden Sie unter Strukturen in WPF.)

Für Eigenschaften, bei denen sowohl Attribut- als auch Eigenschaftenelementsyntax unterstützt werden, haben die beiden Syntaxen im Allgemeinen das gleiche Ergebnis, obwohl Feinheiten wie die Behandlung von Leerzeichen zwischen Syntaxen geringfügig variieren können.

Auflistungssyntax

Die XAML-Spezifikation erfordert XAML-Prozessorimplementierungen, um Eigenschaften zu identifizieren, bei denen der Werttyp eine Auflistung ist. Die allgemeine XAML-Prozessorimplementierungen in .NET basieren auf verwaltetem Code und der CLR und identifizieren Auflistungstypen über einen der folgenden Methoden:

  • Der Typ implementiert IList .

  • Der Typ implementiert IDictionary .

  • Typ wird von abgeleitet Array (weitere Informationen zu Arrays in XAML finden Sie unter Array.)

Wenn der Typ einer Eigenschaft eine Auflistung ist, muss der abgeleitete Auflistungstyp nicht im Markup als Objektelement angegeben werden. Stattdessen werden die Elemente, die als Elemente in der Auflistung dienen sollen, als mindestens ein untergeordnetes Element des Eigenschaftselements angegeben. Jedes dieser Elemente wird während des Ladens zu einem Objekt ausgewertet und der Auflistung hinzugefügt, indem die Add -Methode der impliziten Auflistung aufgerufen wird. Beispielsweise übernimmt die Triggers -Eigenschaft von Style den TriggerCollection spezialisierten Auflistungstyp , der IList implementiert. Es ist nicht erforderlich, ein Objektelement im Markup zu TriggerCollection 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 typisierten und impliziten erwartet TriggerCollection 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. Dies wird im nächsten Abschnitt dieses Themas erläutert.

Ein implizites Auflistungselement erstellt einen Member 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 ihrer Eigenschaften ist, und die anfänglich leere Auflistung wird Teil der Objektstruktur.

Hinweis

Die generischen Listen- und Wörterbuchschnittstellen ( und ) werden für die IList<T>IDictionary<TKey,TValue> Sammlungserkennung nicht unterstützt. Sie können die List<T> -Klasse jedoch als Basisklasse verwenden, da sie direkt implementiert IList wird, oder als Dictionary<TKey,TValue> 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 Auflistungssyntax notiert.

Mit Ausnahme des Stammelements ist jedes Objektelement in einer XAML-Datei, das als untergeordnetes Element eines anderen Elements geschachtelt ist, tatsächlich ein Element, das einer oder beide der folgenden Fälle ist: 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 bevorstehenden Abschnitt erläutert). Anders ausgedrückt: Die Beziehung von übergeordneten Elementen und untergeordneten Elementen auf einer Markupseite ist tatsächlich ein einzelnes Objekt im Stamm, und jedes Objektelement unter dem Stamm ist entweder eine einzelne Instanz, die einen Eigenschaftswert des übergeordneten Elements bereitstellt, oder eines der Elemente innerhalb einer Auflistung, die auch ein Auflistungstyp-Eigenschaftswert des übergeordneten Elements ist. Dieses Single-Root-Konzept ist bei XML üblich und wird häufig im Verhalten von APIs beeinflusst, die XAML laden, z. Load B. .

Im folgenden Beispiel wird eine Syntax mit dem -Objektelement für eine Auflistung ( GradientStopCollection ) explizit angegeben.

<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. Beispielsweise würde der Versuch, explizit im oben gezeigten Beispiel zu deklarieren, TriggerCollectionTriggers fehlschlagen. Das explizite Deklarieren der Auflistung erfordert, dass die Auflistungsklasse einen parameterlosen Konstruktor unterstützen muss und TriggerCollection keinen parameterlosen Konstruktor besitzt.

XAML-Inhaltseigenschaften

Die XAML-Inhaltssyntax ist eine Syntax, die nur für Klassen aktiviert ist, die ContentPropertyAttribute als Teil ihrer Klassendeklaration angeben. ContentPropertyAttributeverweist auf den Eigenschaftennamen, der die Inhaltseigenschaft für diesen Elementtyp (einschließlich abgeleiteter Klassen) ist. Bei der Verarbeitung durch einen XAML-Prozessor werden alle untergeordneten Elemente oder innerer Text, die zwischen den öffnenden und schließenden Tags des Objektelements gefunden werden, dem Wert der XAML-Inhaltseigenschaft für dieses Objekt zugewiesen. Sie können explizite Eigenschaftselemente für die Inhaltseigenschaft angeben, diese Verwendung wird jedoch im Allgemeinen nicht in den XAML-Syntaxabschnitten in der .NET-Referenz gezeigt. Die explizite/ausführliche Technik hat gelegentlich Einen Wert für Markupklarheit oder im Markupstil, aber in der Regel besteht die Absicht einer Inhaltseigenschaft darin, das Markup so zu optimieren, dass Elemente, die intuitiv als über- und untergeordnete Elemente verknüpft sind, direkt geschachtelt werden können. Eigenschaftenelementtags für andere Eigenschaften in einem Element werden nicht als "Inhalt" gemäß einer strengen 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 muss entweder vollständig vor oder vollständig nach anderen Eigenschaftselementen für dieses Objektelement angegeben werden. Dies gilt unabhängig davon, ob der Wert einer XAML-Inhaltseigenschaft als Zeichenfolge oder als ein oder mehrere -Objekte angegeben ist. Das folgende Markup analysiert z. B. nicht:

<Button>I am a
  <Button.Background>Blue</Button.Background>  
  blue button</Button>  

Dies ist im Wesentlichen unzulässig, da die Inhaltseigenschaft zweimal festgelegt wird, wenn diese Syntax mithilfe der Syntax des Eigenschaftselements für die Content-Eigenschaft explizit gemacht würde:

<Button>  
  <Button.Content>I am a </Button.Content>  
  <Button.Background>Blue</Button.Background>  
  <Button.Content> blue button</Button.Content>  
</Button>  

Ein ähnliches unzulässiges Beispiel ist, wenn die Inhaltseigenschaft eine Auflistung ist und untergeordnete Elemente mit Eigenschaftselementen durchsetzt werden:

<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 Content-Eigenschaft speziell ein Auflistungstyp sein. Ähnlich wie bei der Syntax von Eigenschaftselementen für Auflistungstypen muss ein XAML-Prozessor Typen identifizieren, bei denen es sich um Auflistungstypen handelt. 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 Eigenschaftenelement angegeben werden. Daher kann dem offensichtlichen Inhaltsmodell im Markup jetzt mehr als ein untergeordnetes Element als Inhalt zugewiesen sein. Im Folgenden wird die Inhaltssyntax für eine Panel abgeleitete Klasse aufgeführt. 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 Eigenschaftenelement für Children noch das -Element für UIElementCollection das im Markup erforderlich ist. Dies ist ein Entwurfsfeature von XAML, sodass rekursiv enthaltene Elemente, die eine Benutzeroberfläche definieren, intuitiver als Eine Struktur geschachtelter Elemente mit unmittelbaren Beziehungen zwischen über- und untergeordneten Elementen dargestellt werden, ohne zwischen Eigenschaftenelementtags oder Auflistungsobjekten zu suchen. Tatsächlich UIElementCollection kann nicht explizit im Markup als Objektelement angegeben werden. Da die einzige beabsichtigte Verwendung als implizite Auflistung ist, UIElementCollection macht keinen öffentlichen parameterlosen Konstruktor verfügbar und kann daher nicht als Objektelement instanziiert werden.

Kombinieren 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 in einem Objektelement verwendet werden, zusammenhängend sein 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 sofortiges Markup innerhalb eines Objektelements verwenden. Anschließend können Sie Eigenschaftselemente einführen. Oder Sie können ein oder mehrere Eigenschaftselemente, dann Inhalt und dann mehr Eigenschaftselemente angeben. Sobald ein Eigenschaftselement jedoch dem Inhalt folgt, können Sie keinen weiteren Inhalt mehr einführen, sondern nur Eigenschaftselemente hinzufügen.

Diese Anforderung an die Reihenfolge von Inhalten/Eigenschaftenelementen gilt nicht für inneren Text, der als Inhalt verwendet wird. Es ist jedoch immer noch ein guter Markupstil, inneren Text zusammenhängend zu halten, da signifikanter Leerraum im Markup schwer visuell zu erkennen ist, wenn Eigenschaftselemente mit innerem Text durchsetzt sind.

XAML-Namespaces

In keinem der vorherigen 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 andere XAML-Namespaces als den XAML-Standardnamespace angeben und weiterhin eine ähnliche Syntax verwenden. Aber an jeder Stelle, an der eine Klasse benannt wird, auf die innerhalb des XAML-Standardnamespace nicht zugegriffen werden kann, muss diesem Klassennamen das Präfix des XAML-Namespace vorangestellt werden, das dem entsprechenden CLR-Namespace zugeordnet ist. Beispielsweise <custom:Example/> ist die Objektelementsyntax zum Instanziieren einer Instanz der Example -Klasse, wobei der CLR-Namespace, der diese Klasse enthält (und möglicherweise die externen Assemblyinformationen, die Unterstützungstypen enthalten), zuvor dem Präfix zugeordnet custom wurde.

Weitere Informationen zu XAML-Namespaces finden Sie unter XAML-Namespaces und Namespacezuordnung für WPF-XAML.

Markuperweiterungen

XAML definiert eine Markuperweiterungsprogrammierentität, die ein Escapezeichen von der normalen XAML-Prozessorbehandlung von Zeichenfolgenattributwerten oder Objektelementen ermöglicht und die Verarbeitung auf eine Unterstützungsklasse zurücksetzt. Das Zeichen, das eine Markuperweiterung für einen XAML-Prozessor identifiziert, wenn attributsyntax verwendet wird, ist die öffnende geschweifte Klammer ({), gefolgt von einem beliebigen Zeichen außer einer schließenden geschweiften Klammer (}). Die erste Zeichenfolge nach der öffnenden geschweiften Klammer muss auf die Klasse verweisen, die das spezifische Erweiterungsverhalten bereitstellt, wobei der Verweis die Teilzeichenfolge "Extension" auslassen kann, wenn diese Teilzeichenfolge Teil des tatsächlichen Klassennamens ist. Danach kann ein einzelnes Leerzeichen angezeigt werden, und dann wird jedes nachfolgenden Zeichen von der Erweiterungsimplementierung als Eingabe verwendet, bis die schließende geschweifte Klammer gefunden wird.

Die .NET XAML-Implementierung verwendet die MarkupExtension abstrakte -Klasse als Grundlage für alle Markuperweiterungen, die von WPF sowie anderen Frameworks oder Technologien unterstützt werden. Die Markuperweiterungen, die WPF speziell implementiert, sind häufig dazu gedacht, eine Möglichkeit zum Verweisen auf andere vorhandene Objekte oder zum Erstellen von verzögerten Verweisen auf Objekte bereitzustellen, die zur Laufzeit ausgewertet werden. Beispielsweise wird eine einfache WPF-Datenbindung erreicht, indem die {Binding} Markuperweiterung anstelle des Werts angegeben wird, den eine bestimmte Eigenschaft normalerweise annehmen würde. Viele der WPF-Markuperweiterungen ermöglichen eine Attributsyntax für Eigenschaften, bei denen eine Attributsyntax andernfalls nicht möglich wäre. Ein -Objekt ist beispielsweise ein relativ komplexer Typ, der Style eine geschachtelte Reihe von Objekten und Eigenschaften enthält. Stile in WPF werden in der Regel als Ressource in definiert ResourceDictionary und dann über eine der beiden WPF-Markuperweiterungen referenziert, die eine Ressource anfordern. Die Markuperweiterung versieht die Auswertung des Eigenschaftswerts mit einer Ressourcensuche und ermöglicht das Bereitstellen des Werts der Eigenschaft unter Verwendung des Style Typs Style in attributsyntax wie im folgenden Beispiel:

<Button Style="{StaticResource MyStyle}">My button</Button>

Hier StaticResource identifiziert 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 Parameter aus der Erweiterungszeichenfolge den angeforderten ResourceKey deklariert. MyStyle wird erwartet, dass es sich um den MyStyle eines Style als Ressource definierten handelt. Die Verwendung der StaticResource-Markuperweiterung fordert an, dass die Ressource verwendet wird, um den Eigenschaftswert zur Ladezeit über die statische Ressourcens lookup-Logik bereitzustellen.

Weitere Informationen über Markuperweiterungen finden Sie unter Markuperweiterungen und WPF XAML. Eine Referenz zu Markuperweiterungen und anderen XAML-Programmierfunktionen, die in der allgemeinen .NET XAML-Implementierung aktiviert sind, finden Sie unter XAML-Namespace (x:). Sprachfeatures. WPF-spezifische Markuperweiterungen finden Sie unter WPF-XAML-Erweiterungen.

Angefügte Eigenschaften

Angefügte Eigenschaften sind ein in XAML eingeführtes Programmierkonzept, bei dem Eigenschaften im Besitz eines bestimmten Typs sein können und von einem bestimmten Typ definiert werden können, aber als Attribute oder Eigenschaftselemente für jedes Element festgelegt werden. Das primäre Szenario, für das angefügte Eigenschaften vorgesehen sind, besteht darin, untergeordneten Elementen in einer Markupstruktur das Melden von Informationen an ein übergeordnetes Element zu ermöglichen, ohne dass ein umfassend freigegebenes Objektmodell für alle Elemente erforderlich ist. 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 eigener angefügter Eigenschaften finden Sie unter Übersicht über angefügte Eigenschaften.

Angefügte Eigenschaften verwenden eine Syntax, die der Syntax von Eigenschaftselementen ähnelt, da Sie auch einen typeNameangeben. propertyName-Kombination. Es gibt zwei wichtige Unterschiede:

  • Sie können typeNameverwenden. propertyName-Kombination, auch wenn eine angefügte Eigenschaft über Attributsyntax festgelegt wird. Angefügte Eigenschaften sind der einzige Fall, in dem das Qualifizieren des Eigenschaftsnamens eine Anforderung in einer Attributsyntax ist.

  • Sie können auch die Syntax des Eigenschaftselements für angefügte Eigenschaften verwenden. Für die typische Syntax von Eigenschaftselementen ist typeName jedoch das Objektelement, das das Eigenschaftselement enthält. Wenn Sie auf eine angefügte Eigenschaft verweisen, ist typeName die Klasse, die die angefügte Eigenschaft definiert, nicht das enthaltende Objektelement.

Angefügte Ereignisse

Angefügte Ereignisse sind ein weiteres in XAML eingeführtes Programmierkonzept, bei dem Ereignisse durch einen bestimmten Typ definiert werden können, handler jedoch an jedes Objektelement angefügt werden können. In der WOF-Implementierung ist der Typ, der ein angefügtes Ereignis definiert, häufig ein statischer Typ, der einen Dienst definiert. Manchmal werden diese angefügten Ereignisse von einem Routingereignisalias in Typen verfügbar gemacht, die den Dienst verfügbar machen. Handler für angefügte Ereignisse werden über die Attributsyntax angegeben. Wie bei angefügten Ereignissen wird die Attributsyntax für angefügte Ereignisse erweitert, um einen typeNamezuzulassen. eventName-Verwendung, wobei typeName die Klasse ist, die - und -Ereignishandleraccessoren für die angefügte Ereignisinfrastruktur bereitstellt, und eventName der Ereignisname ist.

Aufbau eines XAML-Stammelements

Die folgende Tabelle zeigt ein typisches XAML-Stammelement, das die spezifischen Attribute eines Stammelements enthält:

<Page Öffnen des Objektelements des Stammelements
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" Der STANDARDMÄßIGE XAML-Namespace (WPF)
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" XAML-Namespace der XAML-Sprache
x:Class="ExampleNamespace.ExampleCode" Die partielle Klassendeklaration, die Markup mit jedem CodeBehind verbindet, der für die partielle Klasse definiert ist.
> Ende des Objektelements für den Stamm. Das Objekt ist noch nicht geschlossen, da das Element untergeordnete Elemente enthält.

Optionale und nicht empfohlenen XAML-Verwendungen

In den folgenden Abschnitten werden XAML-Verwendungen beschrieben, die von XAML-Prozessoren technisch unterstützt werden, aber zu ausführlichen oder anderen ansprechenden Problemen führen, die dazu führen, dass XAML-Dateien beim Entwickeln von Anwendungen, die XAML-Quellen enthalten, für Menschen lesbar bleiben.

Optionale Eigenschaftenelementverwendungen

Optionale Eigenschaftenelementverwendungen umfassen das explizite Schreiben von Elementinhaltseigenschaften, die der XAML-Prozessor als implizit betrachtet. Wenn Sie z. B. den Inhalt eines Menu deklarieren, können Sie die Auflistung von explizit als Eigenschaftenelementtag deklarieren Items und diese in Menu<Menu.Items>MenuItem<Menu.Items> platzieren, anstatt das implizite XAML-Prozessorverhalten zu verwenden, bei dem alle untergeordneten Elemente eines Menu ein sein müssen und in der Auflistung platziert MenuItemItems werden. Manchmal können die optionalen Verwendungen dabei helfen, die objektstruktur, wie im Markup dargestellt, visuell zu verdeutlichen. Oder manchmal kann eine explizite Verwendung von Eigenschaftselementen Markup vermeiden, das technisch funktionsfähig, aber visuell verwirrend ist, z. B. geschachtelte Markuperweiterungen innerhalb eines Attributwerts.

Vollständige qualifizierte TypeName.MemberName-Attribute

Der typeName. das elementName-Formular für ein Attribut funktioniert eigentlich universeller als nur der Routingereignisfall. In anderen Situationen ist diese Form jedoch überflüssig, und Sie sollten sie vermeiden, wenn dies nur aus Gründen des Markupstils und der Lesbarkeit erfolgt. Im folgenden Beispiel sind alle drei Verweise auf das Background Attribut vollständig gleichwertig:

<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 für Button erfolgreich ist ( wurde von Control Background geerbt) und Button die Klasse des Objektelements oder einer Basisklasse ist. Control.Background funktioniert, da die Control -Klasse tatsächlich definiert Background und eine ControlButton Basisklasse ist.

Der folgende Typnameist jedoch . Das MemberName-Formularbeispiel funktioniert nicht und wird daher als kommentiert angezeigt:

<!--<Button Label.Background="Blue">Does not work</Button> -->

Label ist eine andere abgeleitete Klasse von Control , und wenn Sie innerhalb eines Label.BackgroundLabel -Objektelements angegeben hätten, hätte diese Verwendung funktioniert. Da jedoch Label nicht die Klasse oder Basisklasse von Button ist, wird das angegebene XAML-Prozessorverhalten Label.Background dann als angefügte Eigenschaft verarbeitet. Label.Background ist keine verfügbare angefügte Eigenschaft, und diese Verwendung schlägt fehl.

baseTypeName.memberName Property Elements

Analog dazu, wie typeNameist. MemberName-Formular funktioniert für attributsyntax, ein baseTypeName. Die memberName-Syntax funktioniert 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 so angegeben, als Control.Background ob das Eigenschaftselement in enthalten Button war.

Aber genau wie typeName. memberName-Formular für Attribute, baseTypeName. memberName ist ein schlechter Stil im Markup, und Sie sollten dies vermeiden.

Siehe auch