Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
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 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 referenziert. XAML ist eine Sprache, die auf XML basiert und auf XML-Strukturregeln folgt oder erweitert. Einige der Begriffe sind aus der Terminologie übernommen oder basieren 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 den Namen impliziert, ermöglicht die Laufzeitausführung. XAML ist selbst nicht eine der gängigen 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 wird der Rest der Diskussion über die Syntax in diesem Dokument Verweise auf das CLR-Typsystem enthalten, auch wenn die entsprechenden Syntaxdiskussionen in der XAML-Sprachspezifikation dies nicht tun. (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 Klassenvererbung
Eigenschaften und Ereignisse, die häufig als XAML-Mitglieder eines WPF-Typs angezeigt werden, werden von Basistypen geerbt. Betrachten Sie z. B. dieses Beispiel: <Button Background="Blue" .../>
. Die Background Eigenschaft ist keine sofort deklarierte Eigenschaft für die Button Klasse, wenn Sie sich die Klassendefinition, Spiegelungsergebnisse oder die Dokumentation ansehen würden. 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ässigen Attributen schwierig genau und vollständig mithilfe der Schema-Typen darzustellen ist, die normalerweise für die XML-Programmierung verwendet werden, z. B. im DTD- oder XSD-Format. Ein weiterer Grund ist, dass Erweiterungs- 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 sie ein XML-Element deklarieren. 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 mindestens ein Leerzeichen für 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 ein innerer Text 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 äquivalente abschließende Tag für das Objektelement muss ebenfalls in ordnungsgemäßer Schachtelung und Balance mit anderen öffnenden und abschließenden Tagpaaren vorliegen.
XAML, das von .NET implementiert wird, verfügt über eine Reihe von Regeln, die Objektelemente in 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 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 Objektelementsyntax, die auch XAML-Inhaltseigenschaftensyntax enthält. Der innere Text, der darin enthalten ist, wird verwendet, um die TextBox XAML-Inhaltseigenschaft festzulegen. Text
<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 ein MenuItem-Element typischerweise nur als untergeordnetes Element einer MenuBase-abgeleiteten Klasse, wie zum Beispiel 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 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.
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 einfache 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 eine 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 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:
Wenn der XAML-Prozessor auf eine geschweifte Klammer oder ein Objektelement, das von MarkupExtension abgeleitet wird, trifft, 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 zum Zeitpunkt der Ausführung verzögert und kein neu instanziiertes Objekt ist.
Wenn die Eigenschaft mit einem Attribut TypeConverterdeklariert wird oder der Werttyp dieser Eigenschaft mit einem Attribut TypeConverterdeklariert wird, wird der Zeichenfolgenwert des Attributs als Konvertierungseingabe an den Typkonverter übermittelt, und der Konverter gibt eine neue Objektinstanz zurück.
Wenn kein TypeConverter vorhanden ist, wird eine direkte Konvertierung in den Eigenschaftstyp versucht. 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 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 nicht im Format Enumeration.Wert an, wie im 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 Form Enumeration.Wert angeben, wird es nicht ordnungsgemäß aufgelöst.
Bei Flagwise-Enumerationen basiert das Verhalten auf der Enum.Parse Methode. Sie können mehrere Werte für eine flagweise 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 ein Trigger-Objekt zu erstellen, das auf mehrere Bedingungen einer Nicht-Flaggen-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"
StyleSimulations = "BoldSimulation,ItalicSimulation"
KeyBinding.Modifiers ist eine andere Eigenschaft, bei der mehrere Enumerationswerte angegeben werden können. Diese Eigenschaft ist jedoch ein Sonderfall, da die ModifierKeys Enumeration 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 bevorstehenden Abschnitt erläutert.)
Sie können auch jedes Ereignis von jedem Objekt referenzieren, auf das über den Standardnamespace zugegriffen werden kann, indem Sie einen teilweise qualifizierten Ereignisnamen mit TypeName.event verwenden; Diese Syntax unterstützt das Anfügen von Handlern für Weiterleitungsereignisse, bei denen der Handler das Routing von Ereignissen von untergeordneten Elementen behandeln soll, aber das übergeordnete Element hat dieses Ereignis nicht in seiner Membertabelle. Diese Syntax ähnelt einer angefügten Ereignissyntax, aber das Ereignis hier ist kein wirklich angefügtes 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 anstelle des Attributnamens als Wert eines Attributs bereitgestellt. Dieser Eigenschaftsname kann auch Qualifizierer enthalten, z. B. die im Formular ownerType angegebene Eigenschaft. dependencyPropertyName. Dieses Szenario tritt häufig auf, wenn man Formatvorlagen 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 "Formatieren und Vorlagen".
Eine weitere Verwendung für Eigenschaftsnamen besteht darin, wenn ein Attributwert eine Beziehung zwischen Eigenschaften beschreibt. Dieses Feature wird für die Datenbindung und für Storyboardziele verwendet und wird von der Klasse und dem PropertyPath zugehörigen Typkonverter aktiviert. Eine ausführlichere Beschreibung der Nachschlagesemantik finden Sie unter PropertyPath XAML-Syntax.
Syntax des Property-Elements
Eigenschaftselementsyntax ist eine Syntax, die etwas 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 Eigenschaftselementsyntax aktiviert. Anstatt dass die Eigenschaft als Attribut innerhalb des Elementtags angegeben wird, wird die Eigenschaft mithilfe eines öffnenden Elementtags in der Form elementTypeName.propertyName angegeben, der Wert der Eigenschaft wird innerhalb festgelegt und dann wird das Eigenschaften-Element 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 wird sofort von einem einzelnen Punkt (.) gefolgt, dann vom Namen einer Eigenschaft und schließlich von einer spitzen Klammer (>). Wie bei der Syntax von Attributen muss die 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, dass die Syntax des Eigenschaftselements adressiert werden soll. Schließlich muss ein gleichwertiges schließendes Tag, das dieselbe elementTypeName.propertyName-Kombination angibt, mit ordnungsgemäßer Schachtelung und Ausgewogenheit im Verhältnis zu anderen Element-Tags bereitgestellt werden.
Das folgende Beispiel ist 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 primitiver Werttyp ist, wie zum Beispiel 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 Zeilenumbrüche beibehalten, aber die Eigenschaftselementsyntax kann es, solange die Erhaltung von signifikantem Leerraum aktiviert ist (ausführliche Informationen finden Sie unter White space processing in XAML). Ein weiteres Szenario besteht darin, dass die x:Uid-Direktive auf das Eigenschaftselement angewendet werden kann und somit den Wert als Wert markieren kann, der in der WPF-Ausgabe BAML oder durch andere Techniken lokalisiert werden soll.
Ein Eigenschaftselement wird nicht in der logischen WPF-Struktur dargestellt. Ein Eigenschaftselement ist nur eine bestimmte Syntax zum Festlegen einer Eigenschaft und kein Element, das eine Instanz oder ein Objekt unterstützt. (Ausführliche Informationen zum logischen Strukturkonzept finden Sie unter "Trees in WPF".)
Bei Eigenschaften, bei denen sowohl attribut- als auch Eigenschaftselementsyntax unterstützt werden, haben die beiden Syntaxen im Allgemeinen dasselbe Ergebnis, obwohl Subtilität wie die Leerraumbehandlung zwischen Syntaxen geringfügig variieren kann.
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 clR und identifiziert Sammlungstypen über einen der folgenden:
Der Typ implementiert IList.
Der Typ implementiert IDictionary.
Der Typ wird abgeleitet von Array (weitere Informationen zu Arrays in XAML finden Sie unter "x:Array Markup Extension".)
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 in der Auflistung werden sollen, als ein oder mehrere untergeordnete Elemente des Eigenschaftselements angegeben. Jedes dieser Elemente wird beim Laden zu einem Objekt ausgewertet und durch Aufruf der Add
-Methode der implizierten Sammlung zur Sammlung hinzugefügt. Beispielsweise nimmt die Triggers-Eigenschaft des Style den spezialisierten Sammlungstyp TriggerCollection, der IList implementiert, an. Es ist nicht erforderlich, ein TriggerCollection Objektelement im Markup zu instanziieren. Stattdessen geben Sie ein oder mehrere Trigger-Elemente als Bestandteil im Style.Triggers
-Eigenschaftselement an, wobei Trigger (oder eine abgeleitete Klasse) der erwartete Typ für den stark typisierten und impliziten TriggerCollection ist.
<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 Element in der logischen Strukturdarstellung, obwohl es nicht im Markup als Element angezeigt wird. In der Regel führt der Konstruktor des Basistyps die Instanziierung einer Auflistung aus, die eine seiner Eigenschaften ist, und die anfänglich leere Auflistung wird Teil des Objektbaums.
Hinweis
Die generischen Listen- und Wörterbuchschnittstellen (IList<T> und IDictionary<TKey,TValue>) werden für die Sammlungserkennung nicht unterstützt. Sie können jedoch die List<T>-Klasse als Basisklasse verwenden, da sie IList direkt implementiert, oder Dictionary<TKey,TValue> als Basisklasse verwenden, 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, die als untergeordnetes Element eines anderen Elements geschachtelt ist, tatsächlich 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). 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 Einzelwurzelkonzept ist bei XML gebräuchlich 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. Der Versuch, TriggerCollection explizit im zuvor gezeigten Triggers Beispiel zu deklarieren, würde 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. Der ContentPropertyAttribute Name der Eigenschaft 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 die Klarheit des Markups oder aus Stilgründen, aber in der Regel besteht die Absicht einer Inhaltseigenschaft darin, das Markup zu optimieren, sodass Elemente, die intuitiv als Eltern-Kind-Elemente verknüpft sind, direkt ineinander verschachtelt 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 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>
Dies ist grundsätzlich illegal, weil, wenn diese Syntax explizit durch die Verwendung der Eigenschaftselementsyntax für die Inhaltseigenschaft gemacht wird, die Inhaltseigenschaft zweimal festgelegt 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 interspersiert 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 Panel abgeleiteten Klassen legen die XAML-Inhaltseigenschaft fest Children, die 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 im Markup weder das Eigenschaftselement für Children noch das Element für UIElementCollection erforderlich ist. Dies ist eine Designeigenschaft von XAML, sodass rekursiv enthaltenen Elemente, die eine Benutzeroberfläche definieren, intuitiver als Baumstruktur von geschachtelten Elementen mit direkten Eltern-Kind-Beziehungen dargestellt werden, ohne dass Eigenschaftselement-Tags oder Sammlungsobjekte eingreifen. Tatsächlich kann UIElementCollection im Markup aus Designgründen nicht explizit als Objektelement angegeben werden. Da die einzige beabsichtigte Verwendung eine implizite Auflistung ist, UIElementCollection wird kein öffentlicher parameterloser Konstruktor verfügbar gemacht 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 ein Eigenschaftselement einem Inhalt folgt, können Sie keinen weiteren Inhalt 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 auffälliger Leerraum im Markup schwer visuell zu erkennen ist, wenn Eigenschaftenelemente mit innerem Text durchmischt sind.
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 überall dort, wo eine Klasse benannt ist, die nicht innerhalb des Standard-XAML-Namespaces zugänglich ist, diesem Klassennamen das Präfix des XAML-Namespaces vorangestellt werden, wie es dem entsprechenden CLR-Namespace zugeordnet ist. Beispielsweise ist <custom:Example/>
die Syntax eines Objektelements, um eine Instanz der Example
Klasse zu erstellen, wobei der CLR-Namespace, der diese Klasse enthält (und möglicherweise die externen Assemblyinformationen, die Sicherungstypen enthalten), zuvor dem custom
Präfix zugeordnet wurde.
Weitere Informationen zu XAML-Namespaces finden Sie unter XAML-Namespaces und Namespacezuordnung für WPF-XAML.
Markuperweiterungen
XAML definiert eine Markup-Erweiterungsprogrammentität, die eine Umgehung der normalen XAML-Prozessorbearbeitung von Zeichenfolgen-Attributwerten oder Objektelementen ermöglicht und die Verarbeitung einer Hintergrundklasse überträgt. Das Zeichen, das eine Markuperweiterung bei Verwendung der Attributsyntax für einen XAML-Prozessor identifiziert, ist die öffnende geschweifte Klammer ({), gefolgt von einem anderen Zeichen als der 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 folgende Zeichen von der Erweiterungsimplementierung als Eingabe aufgegriffen, 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 von WPF speziell implementiert werden, dienen häufig 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 ResourceDictionary definiert und dann über eine der beiden WPF-Markuperweiterungen referenziert, die eine Ressource anfordern. Die Markup-Erweiterung verzögert die Auswertung des Eigenschaftswerts zur Ressourcensuche und ermöglicht die Bereitstellung des Werts der Style Eigenschaft, indem der Typ Style verwendet wird, in der Attribute-Syntax wie im folgenden Beispiel:
<Button Style="{StaticResource MyStyle}">My button</Button>
Hier identifiziert StaticResource
die StaticResourceExtension-Klasse, die die Implementierung der Markuperweiterung bereitstellt. Die nächste Zeichenfolge MyStyle
wird als Eingabe für den nicht-standard StaticResourceExtension Konstruktor verwendet, wobei der Parameter aus der Erweiterungszeichenfolge die angeforderte ResourceKey deklariert wird. Es wird erwartet, dass MyStyle
der x:Key-Wert eines als Ressource definierten Style ist. Die Verwendung der StaticResource-Markuperweiterung fordert an, dass die Ressource verwendet wird, um den Style Eigenschaftswert über statische Ressourcensuchlogik zum Ladezeitpunkt bereitzustellen.
Weitere Informationen zu Markuperweiterungen finden Sie unter Markuperweiterungen und WPF-XAML. Für eine Referenz von Markuperweiterungen und anderen in der allgemeinen .NET-XAML-Implementierung aktivierten XAML-Programmiersprachenfunktionen, siehe XAML-Namespace (x:) Sprachfeatures. Informationen zu WPF-spezifischen Markuperweiterungen finden Sie unter WPF-XAML-Erweiterungen.
Angefügte Eigenschaften
Angefügte Eigenschaften sind ein Programmierkonzept, das in XAML eingeführt wird, wobei Eigenschaften einem bestimmten Typ gehören und 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, 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 weiterzugeben. 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 oberflächlich einer Eigenschaftselementsyntax ähnelt, bei der Sie ebenfalls eine typeName-propertyName-Kombination angeben. Es gibt zwei wichtige Unterschiede:
Sie können die Kombination aus typeName.propertyName auch beim Festlegen einer angefügten Eigenschaft über Attributsyntax verwenden. Angefügte Eigenschaften sind der einzige Fall, wenn das Qualifizieren des Eigenschaftsnamens eine Anforderung in einer Attributsyntax ist.
Sie können auch eigenschaftselementsyntax für angefügte Eigenschaften verwenden. Bei der typischen Eigenschaftselementsyntax ist der angegebene 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 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 durch Attributsyntax angegeben. Wie bei angefügten Ereignissen wird die Attributsyntax für angefügte Ereignisse erweitert, um eine typeName.eventName-Verwendung zu ermöglichen, wobei typeName die Klasse ist, die Add
Ereignishandler-Accessoren für die angefügte Ereignisinfrastruktur bereitstellt, und Remove
der Ereignisname ist.
Anatomie eines XAML-Stammelements
Die folgende Tabelle zeigt ein typisches XAML-Stammelement aufgeschlüsselt und beschreibt die spezifischen Attribute eines Stammelements.
Merkmal | 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 beliebigen Code-Behind verbindet, das für die partielle Klasse definiert ist. |
> |
Ende des Objektelements für den Stamm. 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, die jedoch zur Ausführlichkeit oder zu anderen ästhetischen Problemen führen können, wodurch XAML-Dateien weniger lesbar bleiben, wenn Sie Anwendungen mit XAML-Quellen entwickeln.
Nutzung optionaler Eigenschaftenelemente
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 Items-Auflistung des Menu explizit als <Menu.Items>
-Eigenschaftselementtag deklarieren und jedes MenuItem-Element innerhalb von <Menu.Items>
platzieren, anstatt das implizite XAML-Prozessorverhalten zu verwenden, bei dem alle untergeordneten Elemente eines Menu zwingend 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 Eigenschaftselementverwendung markups vermeiden, die technisch funktionsfähig, aber visuell verwirrend sind, z. B. geschachtelte Markuperweiterungen innerhalb eines Attributwerts.
Vollständige typeName.memberName qualifizierte Attribute
Der typeName.memberName-Form für ein Attribut funktioniert tatsächlich universeller als nur beim Fall eines Routed Events. Aber in anderen Situationen ist dieses Formular überflüssig und Sie sollten es vermeiden, wenn nur aus Gründen des Markupstils und der Lesbarkeit. 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 Abfrage für diese Eigenschaft auf Button erfolgreich ist (Background wurde von Control geerbt), und Button ist die Klasse des Objektelements oder einer Basisklasse.
Control.Background
funktioniert, da die Control Klasse tatsächlich definiert Background und Control eine Button Basisklasse ist.
Der folgende TypeName.memberName-Formularbeispiel funktioniert nicht und wird daher als Kommentar angezeigt:
<!--<Button Label.Background="Blue">Does not work</Button> -->
Labelist eine andere abgeleitete Klasse von Control, und wenn Sie innerhalb eines Label.Background
Objektelements angegeben Label hätten, hätte diese Verwendung funktioniert. Da Label jedoch nicht die Klasse oder Basisklasse von Button ist, wird das angegebene XAML-Prozessorverhalten so ausgeführt, dass Label.Background
als angefügte Eigenschaft verarbeitet wird.
Label.Background
ist keine verfügbare angefügte Eigenschaft, und diese Verwendung schlägt fehl.
baseTypeName.memberName-Eigenschaftselemente
In ähnlicher Weise, wie die typeName.memberName-Syntax für 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 Button
enthalten war.
Aber genau wie typeName.memberName-Format für Attribute, ist baseTypeName.memberName ein schlechter Stil im Markup, und Sie sollten es vermeiden.
Siehe auch
.NET Desktop feedback