Freigeben über


XAML-Syntax im Detail

In diesem Thema werden die Begriffe definiert, die zum Beschreiben der Elemente der XAML-Syntax verwendet werden. Diese Begriffe werden während des restlichen Verlaufs dieser Dokumentation häufig 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 werden. In diesem Thema wird auf die grundlegende Terminologie eingegangen, die im Thema XAML in WPFeingeführt wurde.

Die XAML-Sprachspezifikation

Die hier definierte XAML-Syntaxterminologie wird auch innerhalb der XAML-Sprachspezifikation definiert oder referenziert. XAML ist eine Sprache, die auf XML basiert und auf XML-Strukturregeln folgt oder erweitert. Einige der Begriffe werden geteilt oder basieren auf der Terminologie, die üblicherweise bei der Beschreibung der XML-Sprache oder des XML-Dokumentenobjektmodells verwendet wird.

Laden Sie [MS-XAML] vom Microsoft Download Center herunter, um weitere Informationen zur XAML-Sprachspezifikation zu erhalten.

XAML und CLR

XAML ist eine Markupsprache. Die Common Language Runtime (CLR), wie durch den Namen impliziert, ermöglicht die Laufzeitausführung. XAML ist nicht eine der üblichen Sprachen, die direkt von der CLR-Laufzeitumgebung verwendet werden. Stattdessen können Sie sich XAML als Unterstützung eines eigenen Typsystems 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 der Rest der Besprechungen über die Syntax in diesem Dokument Verweise auf das CLR-Typsystem, auch wenn die entsprechenden Syntaxbesprechungen in der XAML-Sprachspezifikation diese nicht einschließen. (Je nach XAML-Sprachspezifikationsstufe können XAML-Typen einem anderen Typsystem zugeordnet werden, das nicht die CLR sein muss, dies erfordert jedoch die Erstellung und Verwendung eines anderen XAML-Parsers.)

Mitglieder von Typen und der Klassenvererbung

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

Das Klassenvererbungsverhalten von WPF-XAML-Elementen ist eine wesentliche Abkehr von einer schemabasierten Interpretation des 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ässiger Attribute schwierig mithilfe der normalerweise für die XML-Programmierung verwendeten Schematypen, wie im DTD- oder XSD-Format, genau und vollständig darzustellen ist. Ein weiterer Grund ist, dass die Erweiterungs- und Typzuordnungsfunktionen der XAML-Sprache selbst die Vollständigkeit jeder festen Darstellung der zulässigen Typen und Mitglieder ausschließen.

Objektelementsyntax

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

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

  • Das öffnende Tag muss mit einer rechtwinkligen Klammer (>) abgeschlossen werden. Andere Objektelemente, Eigenschaftselemente oder innere Texte können dem öffnenden Tag folgen. Genau der Inhalt, der hier enthalten sein kann, ist in der Regel durch das Objektmodell des Elements eingeschränkt. Das entsprechende Schließtag für das Objektelement muss auch ordnungsgemäß verschachtelt und im Gleichgewicht mit anderen öffnenden und schließenden Tagpaaren vorhanden sein.

XAML, wie es von .NET implementiert wird, verfügt über eine Reihe von Regeln, die Objektelemente in Typen, Attribute in Eigenschaften oder Ereignisse und XAML-Namespaces zu CLR-Namespaces sowie Assemblys zuordnen. Für WPF und .NET werden XAML-Objektelemente den .NET-Typen zugeordnet, wie sie in den referenzierten Assemblys definiert sind, wobei die Attribute Mitglieder der entsprechenden Typen zugeordnet werden. Wenn Sie in XAML auf einen CLR-Typ verweisen, haben Sie auch Zugriff auf die geerbten Member dieses Typs.

Das folgende Beispiel ist beispielsweise eine Objektelementsyntax, die eine neue Instanz der Button-Klasse instanziiert und außerdem ein Name Attribut und einen Wert für dieses Attribut angibt:

<Button Name="CheckoutButton"/>

Das folgende Beispiel ist eine Objekt-Element-Syntax, die auch XAML-Inhaltseigenschafts-Syntax enthält. Der darin enthaltene innere Text wird verwendet, um die TextBox XAML-Inhaltseigenschaft Textfestzulegen.

<TextBox>This is a Text Box</TextBox>

Inhaltsmodelle

Eine Klasse kann eine Verwendung als XAML-Objektelement in Bezug auf die Syntax unterstützen, dieses Element funktioniert jedoch nur ordnungsgemäß in einer Anwendung oder Seite, wenn es an einer erwarteten Position eines allgemeinen Inhaltsmodells oder einer Elementstruktur platziert wird. Beispielsweise sollte eine MenuItem in der Regel nur als untergeordnetes Element einer MenuBase abgeleiteten Klasse wie Menuplatziert 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 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 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. Auf den Attributnamen folgt ein Zuordnungsoperator (=). Der Attributwert muss eine Zeichenfolge sein, die in Anführungszeichen eingeschlossen ist.

Anmerkung

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 einfache oder doppelte Anführungszeichen verwenden, sollten Sie ein übereinstimmendes Paar zum Öffnen und Schließen der Attributwertzeichenfolge nutzen. Es gibt auch Escapesequenzen oder andere Techniken, um Zeicheneinschränkungen zu umgehen, die von einer bestimmten XAML-Syntax auferlegt werden. Siehe XML-Zeichenentitäten und XAML.

Damit eine Eigenschaft über Attributsyntax gesetzt werden kann, muss sie öffentlich und schreibbar sein. Der Wert der Eigenschaft im Basistypensystem muss entweder ein Werttyp oder ein Verweistyp sein, welcher von einem XAML-Prozessor instanziiert oder referenziert werden kann, wenn auf den relevanten Basistyp 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 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 anhand dieser Verarbeitungsreihenfolge durch eine der folgenden Werte gefüllt:

  1. Wenn der XAML-Prozessor auf eine geschweifte Klammer oder ein Objektelement trifft, das von MarkupExtensionabgeleitet 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 verzögert und kein neu instanziiertes Objekt ist.

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

  3. Wenn keine TypeConvertervorhanden ist, wird versucht, eine direkte Konvertierung in den Eigenschaftentyp durchzuführen. Diese letzte Ebene ist eine direkte Konvertierung beim 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).

Enumeration-Attributwerte

Enumerationen in XAML werden intern von XAML-Parsern verarbeitet, und die Mitglieder einer Enumeration sollten durch die Angabe des Zeichenfolgennamens einer der benannten Konstanten der Enumeration ausgewählt werden.

Bei Nichtflag-Enumerationswerten besteht das systemeigene Verhalten darin, die Zeichenfolge eines Attributwerts zu verarbeiten und in einen der Enumerationswerte aufzulösen. Sie spezifizieren die Aufzählung nicht im Format Enumeration,Wert, so wie Sie es im Code tun. Stattdessen geben Sie nur Wertan, und Enumeration wird vom Typ der Eigenschaft abgeleitet, die Sie festlegen. Wenn Sie ein Attribut in der EnumerationForm Wert angeben, kann es nicht richtig aufgelöst werden.

Bei flagweisen Enumerationen basiert das Verhalten auf der Enum.Parse-Methode. Sie können mehrere Werte für eine Flag-Enumeration angeben, indem Sie jeden Wert durch ein Komma trennen. Enumerationswerte, die nicht flagweise sind, können jedoch nicht kombiniert werden. Sie können z. B. die Kommasyntax nicht verwenden, um zu versuchen, eine Trigger zu erstellen, die auf mehrere Bedingungen einer Nichtflag-Aufzählung 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 werden können, sind in WPF selten. Eine solche Aufzählung ist jedoch StyleSimulations. Sie können z. B. die durch Trennzeichen getrennte Attributsyntax verwenden, um das in den Hinweisen für die Glyphs-Klasse angegebene Beispiel zu ändern; 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-Aufzählung einen 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-Programmierung darzustellen, z. B. "STRG+ALT".

Eigenschaften- und Ereigniselementnamenverweise

Beim Angeben eines Attributs können Sie auf eine beliebige Eigenschaft oder jedes Ereignis verweisen, das als Mitglied 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 kommenden Abschnitt erläutert.)

Sie können auch ein beliebiges Ereignis von einem Objekt benennen, auf das über den Standardnamespace zugegriffen werden kann, indem Sie einen typeNameverwenden:Ereignis teilweise qualifizierter Name; Diese Syntax unterstützt das Anfügen von Handlern für geroutete Ereignisse, bei denen der Handler das Routing von Ereignissen von untergeordneten Elementen behandeln soll, jedoch hat das übergeordnete Element dieses Ereignis nicht in seiner Membertabelle. Diese Syntax ähnelt einer angeschlossenen Ereignissyntax, aber das Ereignis hier ist kein wirklich angeschlossenes Ereignis. Stattdessen verweisen Sie auf ein Ereignis mit einem qualifizierten Namen. Weitere Informationen finden Sie unter Übersicht über geroutete Ereignisse.

In einigen Szenarien werden Eigenschaftsnamen manchmal anstelle des Attributnamens als Wert eines Attributs bereitgestellt. Dieser Eigenschaftsname kann auch Qualifizierer enthalten, z. B. die im Formular angegebene Eigenschaft ownerType.dependencyPropertyName. Dieses Szenario ist häufig, wenn man Stile oder Vorlagen in XAML schreibt. Die Verarbeitungsregeln für Eigenschaftsnamen, die als Attributwert bereitgestellt werden, unterscheiden sich und unterliegen dem Typ der festzulegenden Eigenschaft oder dem Verhalten bestimmter WPF-Subsysteme. Ausführliche Informationen finden Sie unter Styling und Templating.

Eine weitere Verwendung von Eigenschaftsnamen ergibt sich, wenn ein Attributwert eine Beziehung zwischen Eigenschaften beschreibt. Dieses Feature wird für die Datenbindung und für Storyboard-Ziele verwendet und wird durch die PropertyPath-Klasse und ihren Typkonverter aktiviert. Eine ausführlichere Beschreibung der Abfrage-Semantik finden Sie unter PropertyPath XAML Syntax.

Syntax des Property-Elements

Eigenschaftselementsyntax ist eine Syntax, die sich 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 Variation darin besteht, welches Zeichenfolgencodierungsformat verwendet wird. In XAML können Sie anderen Objektelementen den Wert einer Eigenschaft zuweisen. Diese Funktion wird durch die Eigenschaftselementsyntax aktiviert. Anstatt die Eigenschaft als Attribut innerhalb des Elementtags anzugeben, wird sie mithilfe eines öffnenden Elementtags im elementTypeNamepropertyName-Format angegeben. Der Wert der Eigenschaft wird innerhalb spezifiziert, und dann wird das Eigenschaftselement geschlossen.

Insbesondere beginnt die Syntax mit einer linken winkeligen Klammer (<), 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 rechtwinklige Klammer (>). Wie bei der Attributsyntax muss diese Eigenschaft zu den deklarierten öffentlichen Mitgliedern des angegebenen Typs gehören. Der wert, der der Eigenschaft zugewiesen werden soll, ist im Eigenschaftselement enthalten. In der Regel wird der Wert als ein oder mehrere Objektelemente angegeben, da das Angeben von Objekten als Werte das Szenario ist, das die Syntax des Eigenschaftselements behandeln soll. Schließlich muss ein gleichwertiges schließendes Tag bereitgestellt werden, das das gleiche elementTypeName,propertyName Kombination angibt, in ordnungsgemäßer Schachtelung und Balance mit anderen Element-Tags.

Das folgende Beispiel ist die Eigenschaftselementsyntax für die eigenschaft ContextMenu 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 Eigenschaftselements kann auch als innerer Text angegeben werden, in Fällen, in denen der angegebene Eigenschaftstyp ein Grundtyp ist, z. B. String, oder eine Aufzählung, in der ein Name angegeben wird. Diese beiden Verwendungen sind etwas ungewöhnlich, da in jedem dieser Fälle auch eine einfachere Attributsyntax verwendet werden kann. 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 Leerraumelemente wie Zeilenfeeds müssen in diesem UI-Text angezeigt werden. Die Attributsyntax kann keine Zeilenfeeds beibehalten, die Eigenschaftselementsyntax kann jedoch aktiv sein, solange die Erhaltung des Leerraums erheblich ist (ausführliche Informationen finden Sie unter Verarbeitung von Leerraum in XAML-). Ein weiteres Szenario besteht darin, dass die x:Uid-Direktive auf das Eigenschaftselement angewendet werden kann, um den Wert innerhalb als zu lokalisierenden Wert in der WPF-Ausgabe BAML oder durch andere Verfahren zu kennzeichnen.

Ein Eigenschafts-Element wird nicht im logischen WPF-Baum dargestellt. Ein Eigenschaftselement ist nur eine bestimmte Syntax zum Festlegen einer Eigenschaft und kein Element, das durch eine Instanz oder ein Objekt unterstützt wird. (Ausführliche Informationen zum logischen Baumkonzept finden Sie unter Trees in WPF.)

Bei Eigenschaften, bei denen sowohl Attribut- als auch Eigenschaftselementsyntax unterstützt werden, haben die beiden Syntaxvarianten im Allgemeinen dasselbe Ergebnis, obwohl Subtilitäten wie die Leerraumbehandlung zwischen den Syntaxvarianten geringfügig variieren können.

Sammlungssyntax

Die XAML-Spezifikation erfordert XAML-Prozessorimplementierungen, um Eigenschaften zu identifizieren, bei denen der Werttyp eine Sammlung ist. Die allgemeine XAML-Prozessorimplementierung in .NET basiert auf verwaltetem Code und der CLR und identifiziert Sammlungstypen über eine der folgenden Methoden:

Wenn es sich bei dem Typ einer Eigenschaft um eine Auflistung handelt, muss der abgeleitete Auflistungstyp im Markup nicht als Objektelement angegeben werden. Stattdessen werden die Elemente, die zu den Elementen der Sammlung werden sollen, als ein oder mehrere untergeordnete Elemente des Eigenschaften-Elements angegeben. Jedes dieser Elemente wird beim Laden zu einem Objekt ausgewertet und zur Sammlung hinzugefügt, indem die Add Methode der implizierten Sammlung aufgerufen wird. Beispielsweise übernimmt die Triggers-Eigenschaft von Style den spezialisierten Sammlungstyp TriggerCollection, der IListimplementiert. Es ist nicht erforderlich, ein TriggerCollection-Objektelement im Markup zu instanziieren. Stattdessen geben Sie ein oder mehrere Trigger-Elemente als Bestandteile des Style.Triggers-Eigenschaftselements an, wobei Trigger (oder eine abgeleitete Klasse) der erwartete Typ für den stark typisierten und impliziten TriggerCollectionist.

<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 Sammlungstyp 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 Mitglied 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 Sammlung durch, die eine seiner Eigenschaften ist, und die anfänglich leere Sammlung wird Teil des Objektbaums.

Anmerkung

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

Mit Ausnahme des Stammelements ist jedes Objektelement in einer XAML-Datei, das als Unterelement eines anderen Elements geschachtelt ist, tatsächlich ein Element, das in einem oder beiden der folgenden Fälle zutrifft: Es ist entweder ein Bestandteil einer impliziten Sammlungseigenschaft 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). Mit anderen Worten, die Beziehung von übergeordneten Elementen und untergeordneten Elementen in einer Markupseite ist wirklich ein einzelnes Objekt am 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 Eigenschaftswert vom Typ "Collection" des übergeordneten Elements ist. Dieses Konzept eines einzelnen Wurzels ist bei XML üblich und wird häufig durch das Verhalten von APIs verstärkt, die XAML, wie zum Beispiel Load, laden.

Das folgende Beispiel ist eine Syntax, bei der das Objektelement für eine Auflistung (GradientStopCollection) explizit angegeben ist.

<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. Wenn Sie beispielsweise versuchen, TriggerCollection explizit im zuvor gezeigten Beispiel Triggers zu deklarieren, schlägt dies fehl. 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 die ContentPropertyAttribute als Teil ihrer Klassendeklaration angeben. Die ContentPropertyAttribute verweist auf den Namen der Eigenschaft, die als Inhaltseigenschaft für diesen Elementtyp dient (einschließlich abgeleiteter Klassen). Bei der Verarbeitung durch einen XAML-Prozessor werden alle untergeordneten Elemente oder inneren Texte, die zwischen den öffnenden und schließenden Tags des Objekt-Elements gefunden werden, als 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 der .NET-Referenz nicht allgemein angezeigt. Die explizite/ausführliche Technik hat gelegentlich Wert für die Klarheit des Markups oder als Frage des Markupstils, aber in der Regel ist es das Ziel einer Inhaltseigenschaft, das Markup so zu vereinfachen, dass Elemente, die intuitiv als Eltern-Kind-Elemente verbunden sind, direkt geschachtelt werden können. Eigenschaftselementtags für andere Eigenschaften eines Elements werden gemäß der strengen XAML-Sprachdefinition nicht als "Inhalt" zugewiesen; sie werden bereits zuvor in der Verarbeitungsreihenfolge des XAML-Parsers verarbeitet und werden nicht als "Inhalt" betrachtet.

XAML-Inhaltseigenschaftswerte müssen zusammenhängend sein

Der Wert einer XAML-Inhaltseigenschaft muss entweder vollständig vor oder vollständig nach anderen Eigenschaftselementen in diesem Objektelement angegeben werden. Dies gilt, ob der Wert einer XAML-Inhaltseigenschaft als Zeichenfolge oder als ein oder mehrere Objekte angegeben wird. Das folgende Markup analysiert z. B. nicht:

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

Es ist im Wesentlichen unzulässig, weil die Inhaltseigenschaft zweimal festgelegt würde, wenn diese Syntax explizit durch die Verwendung der Eigenschaftselementsyntax für die Inhaltseigenschaft gemacht würde.

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

Ein ähnlich unzulässiges Beispiel ist, wenn es sich bei der Inhaltseigenschaft um eine Auflistung handelt, und untergeordnete Elemente mit Eigenschaftselementen vermischt werden:

<StackPanel>  
  <Button>This example</Button>  
  <StackPanel.Resources>  
    <SolidColorBrush x:Key="BlueBrush" Color="Blue"/>  
  </StackPanel.Resources>  
  <Button>... is illegal XAML</Button>  
</StackPanel>  

Kombinierte Inhaltseigenschaften und Sammlungssyntax

Um mehr als ein einzelnes Objektelement als Inhalt zu akzeptieren, muss der Typ der Inhaltseigenschaft speziell ein Sammlungstyp sein. Ähnlich wie die Eigenschaftselementsyntax für Sammlungstypen 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 implizierte Sammlungstyp 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 eine Inhaltssyntax für eine Panel abgeleitete Klasse. Alle von Panel abgeleiteten Klassen legen die XAML-Inhaltseigenschaft auf Childrenfest, was einen Wert vom Typ UIElementCollectionerfordert.

<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 Baum von geschachtelten Elementen mit unmittelbaren Beziehungen zwischen übergeordneten und untergeordneten Elementen dargestellt werden, ohne Verwendung von Eigenschaftselement-Tags oder Auflistungsobjekten. Tatsächlich kann UIElementCollection nicht explizit im Markup als Object-Element angegeben werden. Da die einzige beabsichtigte Verwendung eine implizite Auflistung ist, 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 müssen. Diese Einschränkung beim 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, dann Inhalt und dann weitere Eigenschaftselemente angeben. Sobald jedoch einem Inhalt ein Eigenschaftselement folgt, können Sie keine weiteren Inhalte hinzufügen, sondern nur noch Eigenschaftselemente.

Diese Anforderung der Inhalts-/Eigenschaftselementreihenfolge gilt nicht für inneren Text, der als Inhalt verwendet wird. Es ist jedoch weiterhin ein guter Markup-Stil, den inneren Text zusammenhängend zu halten, da signifikanter Leerraum im Markup visuell schwer zu erkennen ist, wenn Eigenschaftselemente mit innerem Text vermischt werden.

XAML-Namespaces

Keiner der vorherigen Syntaxbeispiele hat einen anderen XAML-Namespace als den standardmäßigen 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 standardmäßigen XAML-Namespace angeben und dennoch eine ähnliche Syntax verwenden. Aber dann muss an einer beliebigen Stelle, an der eine Klasse benannt ist, die nicht innerhalb des standardmäßigen XAML-Namespace zugänglich ist, diesem Klassennamen das Präfix des XAML-Namespace vorangestellt werden, wie dem entsprechenden CLR-Namespace zugeordnet. Beispielsweise ist <custom:Example/> die Syntax eines Objektelements, um eine Instanz der Klasse Example zu erstellen, wobei der CLR-Namespace, der diese Klasse enthält (und möglicherweise die externen Assemblyinformationen, die unterstützende Typen umfasst), zuvor dem Präfix custom zugeordnet wurde.

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

Markuperweiterungen

XAML definiert eine Markup-Erweiterungsprogrammiereinheit, die das normale XAML-Prozessorhandling von Zeichenfolgen-Attributwerten oder Objekten umgeht und die Verarbeitung an eine Hintergrundklasse übergibt. Das Zeichen, das eine Markup-Erweiterung für einen XAML-Prozessor identifiziert, wenn die Attributsyntax verwendet wird, ist die öffnende geschweifte Klammer ({), gefolgt von jedem anderen Zeichen als einer schließenden geschweiften Klammer (}). Die erste Zeichenfolge nach der öffnenden geschweiften Klammer muss auf die Klasse verweisen, die das bestimmte Erweiterungsverhalten bereitstellt, wobei der Verweis die Teilzeichenfolge "Extension" auslassen kann, wenn diese Teilzeichenfolge Teil des tatsächlichen Klassennamens ist. Danach kann ein einzelnes Leerzeichen erscheinen, und dann wird jedes nachfolgende Zeichen von der Erweiterungsimplementierung verarbeitet, bis die schließende geschweifte Klammer auftritt.

Die .NET-XAML-Implementierung verwendet die abstrakte Klasse MarkupExtension als Grundlage für alle von WPF unterstützten Markup-Erweiterungen sowie für andere unterstützende Frameworks und Technologien. Häufig dienen die Markuperweiterungen, die speziell von WPF implementiert werden, dazu, auf andere vorhandene Objekte zu verweisen oder zurückgestellte Verweise auf Objekte zu erstellen, 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 übernehmen würde. Viele der WPF-Markuperweiterungen ermöglichen eine Attributsyntax für Eigenschaften, bei denen eine Attributsyntax andernfalls nicht möglich wäre. Ein Style-Objekt ist beispielsweise ein relativ komplexer Typ, der eine geschachtelte Reihe von Objekten und Eigenschaften enthält. Formatvorlagen in WPF werden in der Regel als Ressource in einem ResourceDictionarydefiniert und dann durch eine der beiden WPF-Markuperweiterungen referenziert, die eine Ressource anfordern. Die Markuperweiterung verzögert die Auswertung des Eigenschaftswerts zu einer Ressourcensuche und ermöglicht die Bereitstellung des Werts der Style-Eigenschaft unter Verwendung von Typ Stylein Attributsyntax, wie im folgenden Beispiel gezeigt:

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

Hier identifiziert StaticResource die StaticResourceExtension klasse, die die Markup-Erweiterungsimplementierung bereitstellt. Die nächste Zeichenfolge MyStyle wird als Eingabe für den nicht standardmäßigen StaticResourceExtension-Konstruktor verwendet, wobei der Parameter, der aus der Erweiterungszeichenfolge entnommen wird, die angeforderte ResourceKeyangibt. Es wird erwartet, dass MyStyle der x:Key Wert eines Style, der als Ressource definiert ist, ist. Die StaticResource-Markuperweiterung fordert, dass die Ressource den Eigenschaftswert Style beim Laden über statische Ressourcensuchlogik bereitstellt.

Weitere Informationen zu Markuperweiterungen finden Sie unter Markuperweiterungen und WPF XAML. Eine Referenz zu Markuperweiterungen und anderen in der Standard .NET-XAML-Implementierung aktivierten XAML-Programmierfeatures finden Sie unter XAML-Namespace (x:) Sprachfeatures. Informationen zu WPF-spezifischen Markuperweiterungen finden Sie unter WPF-XAML-Erweiterungen.

Angefügte Eigenschaften

Angeheftete Eigenschaften sind ein Programmierkonzept, das in XAML eingeführt wird, bei dem Eigenschaften einem bestimmten Typ zugeordnet und definiert werden, aber als Attribute oder Eigenschaftselemente an 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 dass für alle Elemente ein umfassend freigegebenes Objektmodell erforderlich ist. Umgekehrt können angefügte Eigenschaften von übergeordneten Elementen verwendet werden, um Informationen an untergeordnete Elemente zu übermitteln. 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 einer Eigenschaftselementsyntax oberflächlich ähnelt, bei der Sie auch eine Kombination aus typeName-,propertyName angeben. Es gibt zwei wichtige Unterschiede:

  • Sie können die Kombination aus typeName-undpropertyName- auch beim Festlegen einer angefügten Eigenschaft über die Attributsyntax verwenden. Angefügte Eigenschaften sind der einzige Fall, bei der die Angabe des Eigenschaftsnamens eine Anforderung in einer Attributsyntax ist.

  • Sie können auch die Eigenschaftselementsyntax für angefügte Eigenschaften verwenden. Bei der typischen Eigenschaftselementsyntax ist der angegebene typeName 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 für jedes 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 Routingereignisalias in Typen verfügbar gemacht, die den Dienst verfügbar machen. Handler für angefügte Ereignisse werden mithilfe von Attributsyntax festgelegt. Wie bei angefügten Ereignissen wird die Attributsyntax für angefügte Ereignisse erweitert, um eine Verwendung der typeName. Syntax zuzulassen, wobei typeName die Klasse ist, die Add und Remove Ereignishandleraccessoren für die angefügte Ereignisinfrastruktur bereitstellt, und eventName der Ereignisname ist.

Anatomie eines XAML-Stammelements

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

Attribut Beschreibung
<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" Der XAML-Sprach-XAML-Namespace
x:Class="ExampleNamespace.ExampleCode" Die partielle Klassendeklaration, die Markup mit einem Code-Behind verbindet, das für die partielle Klasse definiert ist.
> Ende des Objektelements für die Wurzel. Objekt ist noch nicht geschlossen, da das Element untergeordnete Elemente enthält.

Optionale und nicht empfohlene XAML-Verwendungen

In den folgenden Abschnitten werden XAML-Verwendungen beschrieben, die technisch von XAML-Prozessoren unterstützt werden, aber Ausführlichkeit oder andere ästhetische Probleme erzeugen, die XAML-Dateien beeinträchtigen können, sodass sie beim Entwickeln von Anwendungen mit XAML-Quellen weniger verständlich bleiben.

Verwendungen von Eigenschaftselementen (optional)

Verwendungen von optionalen Eigenschaftselementen umfassen das explizite Schreiben von Eigenschaften des Elementinhalts, die der XAML-Prozessor als implizit betrachtet. Wenn Sie beispielsweise den Inhalt eines Menudeklarieren, können Sie die Items-Auflistung des Menu explizit als ein Tag für Eigenschaftselemente <Menu.Items> deklarieren und jedes MenuItem innerhalb von <Menu.Items>platzieren, anstatt das implizite XAML-Prozessorverhalten zu verwenden, dass alle untergeordneten Elemente von Menu ein MenuItem sein müssen und in der Items-Auflistung platziert werden. Manchmal können die optionalen Verwendungen dazu beitragen, die Objektstruktur visuell zu verdeutlichen, wie im Markup dargestellt. Oder manchmal kann eine explizite Eigenschafts-Elementverwendung ein Markup vermeiden, das technisch funktionsfähig, aber visuell verwirrend ist, z. B. geschachtelte Markuperweiterungen innerhalb eines Attributwerts.

Vollständig qualifizierte typeName.memberName-Attribute

Der typeName-.MemberName Formular für ein Attribut funktioniert tatsächlich universeller als nur der Routingereignisfall. Aber in anderen Situationen ist diese Form überflüssig und Sie sollten sie vermeiden, auch wenn es nur aus Gründen des Markup-Stils und der Lesbarkeit ist. Im folgenden Beispiel sind alle drei Verweise auf das attribut Background 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 nach dieser Eigenschaft bei Button erfolgreich ist (Background wurde von Control geerbt) und Button die Klasse des Objektelements oder einer Basisklasse ist. Control.Background funktioniert, da die Control Klasse tatsächlich Background definiert und Control eine Button Basisklasse ist.

Der folgende typeName.memberName Formularbeispiel funktioniert nicht und wird daher in kommentierter Form gezeigt:

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

Label ist eine andere abgeleitete Klasse von Control, und wenn Sie Label.Background innerhalb eines Label-Objektelements angegeben hätten, wäre diese Verwendung möglich gewesen. Da Label jedoch nicht die Klasse oder Basisklasse von Buttonist, besteht das angegebene XAML-Prozessorverhalten darin, Label.Background als angefügte Eigenschaft zu verarbeiten. Label.Background ist keine verfügbare angefügte Eigenschaft, und diese Verwendung schlägt fehl.

baseTypeName.memberName-Eigenschaftselemente

Analog dazu, wie der typeName.memberName -Formular für die Attributsyntax funktioniert, funktioniert eine baseTypeName.memberName -Syntax für die Eigenschaftselementsyntax. Die folgende Syntax funktioniert beispielsweise:

<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 Buttonenthalten war.

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

Siehe auch