Freigeben über


Markuperweiterungen und WPF-XAML

Dieses Thema bietet eine Einführung in das Konzept der Markuperweiterungen für XAML und enthält eine Erläuterung der Syntaxregeln, des Zwecks und des zugrunde liegenden Klassenobjektmodells. Markuperweiterungen sind eine allgemeine Funktion der XAML-Sprache und der .NET-Implementierung von XAML-Diensten. In diesem Thema werden speziell Markuperweiterungen zur Verwendung in WPF-XAML beschrieben.

Dieses Thema enthält folgende Abschnitte.

  • XAML-Prozessoren und Markuperweiterungen
  • Grundlegende Markuperweiterungssyntax
  • XAML-definierte Markuperweiterungen
  • WPF-spezifische Markuperweiterungen
  • *Erweiterungsklassen
  • Escapesequenzen und Markuperweiterungen
  • Schachtelung von Markuperweiterungen in der XAML-Verwendung
  • Markuperweiterungen und Eigenschaftenelementsyntax
  • Verwandte Abschnitte

XAML-Prozessoren und Markuperweiterungen

Im Allgemeinen kann ein XAML-Parser einen Attributwert entweder als Literalzeichenfolge interpretieren, die in eine Primitive konvertiert werden kann, oder auf bestimmte Weise in ein Objekt konvertieren. Eine Möglichkeit ist das Verweisen auf einen Typkonverter; dies wird im Thema TypeConverter und XAML dokumentiert. In bestimmten Szenarios ist jedoch ein anderes Verhalten erforderlich. Ein XAML-Prozessor kann z. B. angewiesen werden, dass der Wert eines Attributs nicht zu einem neuen Objekt im Objektdiagramm führen soll. Stattdessen soll das Attribut ein Objektdiagramm ergeben, das auf ein bereits erstelltes Objekt in einem anderen Teil des Diagramms oder auf ein statisches Objekt verweist. Ein anderes Szenario ist, dass ein XAML-Prozessor angewiesen werden kann, Syntax zu verwenden, die für den Konstruktor eines Objekts nicht standardmäßige Argumente bereitstellt. Diese sind die Typen von Szenarien, in denen die Lösung mit einer Markuperweiterung bereitgestellt werden kann.

Grundlegende Markuperweiterungssyntax

Eine Markuperweiterung kann implementiert werden, um Werte für Eigenschaften bei Verwendung von Attributen oder Eigenschaften bei Verwendung von Eigenschaftenelementen bereitzustellen oder beides.

Bei Verwendung der Markuperweiterungssequenz zum Bereitstellen eines Attributwerts wird diese durch öffnende und schließende geschweifte Klammern ({ und }) für den XAML-Prozessor kenntlich gemacht. Der Typ der Markuperweiterung wird durch das Zeichenfolgentoken angegeben, das unmittelbar auf die öffnende geschweifte Klammer folgt.

Bei Verwendung in Eigenschaftenelementsyntax entspricht das Erscheinungsbild der Markuperweiterung einem Element, das zum Bereitstellen eines Eigenschaftenelementwerts verwendet wird: eine XAML-Elementdeklaration, die auf die Markuperweiterungsklasse als Element verweist und von spitzen Klammern (<>) umschlossen ist.

XAML-definierte Markuperweiterungen

Es gibt mehrere Markuperweiterungen, die nicht spezifisch für die WPF-Implementierung von XAML gelten, sondern Implementierungen für Funktionen von XAML als Sprache sind. Diese Markuperweiterungen werden als Teil der allgemeinen .NET Framework-XAML-Dienste in der System.Xaml-Assembly implementiert und sind im XAML-Sprachnamespace enthalten. Im Hinblick auf die allgemeine Markupverwendung sind diese Markuperweiterungen in der Regel durch das x:-Präfix in der Verwendung identifizierbar. Die MarkupExtension-Basisklasse (auch in "System.Xaml" definiert) stellt das Muster bereit, das für alle Markuperweiterungen verwendet werden sollte, damit sie in den XAML-Readern und XAML-Writern (einschließlich WPF-XAML) unterstützt werden.

  • x:Type stellt das Type-Objekt für den benannten Typ bereit. Diese Funktion wird am häufigsten in Stilen und Vorlagen verwendet. Weitere Informationen finden Sie unter x:Type-Markuperweiterung.

  • x:Static erzeugt statische Werte. Die Werte stammen aus Wert-Typ-Codeentitäten, die nicht direkt dem Typ eines Zieleigenschaftswerts entsprechen, jedoch diesem Typ entsprechend ausgewertet werden können. Weitere Informationen finden Sie unter x:Statische Markuperweiterung.

  • x:Null gibt null als Wert für eine Eigenschaft an und kann für Attribute oder Eigenschaftenelementwerte verwendet werden. Weitere Informationen finden Sie unter x:Null-Markuperweiterung.

  • x:Array bietet Unterstützung für die Erstellung von allgemeinen Arrays in XAML-Syntax, wenn die Auflistungsunterstützung von WPF-Basiselementen und Steuerelementmodellen nicht verwendet wird. Nähere Informationen finden Sie unter x:Array-Markuperweiterung.

HinweisHinweis

Das x:-Präfix wird für die typische XAML-Namespacezuordnung des systeminternen XAML-Sprachnamespace im Stammelement einer XAML-Datei oder -Produktion verwendet.Beispiel: Visual Studio-Vorlagen für WPF-Anwendungen initiieren eine XAML-Datei mit dieser x:-Zuordnung.Sie können ein anderes Präfixtoken in Ihrer eigenen XAML-Namespacezuordnung auswählen, in dieser Dokumentation wird jedoch die x:-Standardzuordnung für die Identifizierung der Entitäten vorausgesetzt, die als Teil des XAML-Sprachnamespace definiert sind (im Gegensatz zu einem standardmäßigen WPF-Namespace oder anderen XAML-Namespaces, die keinem bestimmten Framework zugeordnet sind).

WPF-spezifische Markuperweiterungen

Bei der WPF-Programmierung werden am häufigsten Markuperweiterungen verwendet, die Ressourcenverweise (StaticResource und DynamicResource) und Datenbindungen (Binding) unterstützen.

  • StaticResource stellt einen Wert für eine Eigenschaft bereit, indem der Wert einer bereits definierten Ressource ersetzt wird. Eine StaticResource-Auswertung wird letztlich zur XAML-Ladezeit vorgenommen und hat während der tatsächlichen Laufzeit keinen Zugriff auf das Objektdiagramm. Weitere Informationen finden Sie unter StaticResource-Markuperweiterung.

  • DynamicResource stellt einen Wert für eine Eigenschaft bereit, indem dieser Wert als Laufzeitverweis auf eine Ressource verwendet wird. Ein dynamischer Ressourcenverweis erzwingt jedes Mal eine neue Suche, wenn auf eine solche Ressource zugegriffen wird und diese zur Laufzeit Zugriff auf das Objektdiagramm hat. Um diesen Zugriff abzurufen, wird das DynamicResource-Konzept von Abhängigkeitseigenschaften im WPF-Eigenschaftensystem und ausgewerteten Ausdrücken unterstützt. Daher kann DynamicResource nur für ein Abhängigkeitseigenschaftsziel verwendet werden. Weitere Informationen finden Sie unter DynamicResource-Markuperweiterung.

  • Binding stellt einen datengebundenen Wert für eine Eigenschaft anhand des Datenkontexts bereit, der zur Laufzeit für das übergeordnete Objekt gilt. Diese Markuperweiterung ist relativ komplex, da sie eine komplexe Inlinesyntax für die Angabe einer Datenbindung aktiviert. Nähere Informationen finden Sie unter Bindung als Markuperweiterung.

  • RelativeSource stellt Quellinformationen für eine Binding bereit, wobei in der Laufzeitobjektstruktur durch mehrere mögliche Beziehungen navigiert werden kann. Hierdurch werden spezielle Quellbezüge für Bindungen bereitgestellt, die in Mehrzweckvorlagen oder in Code ohne vollständige Kenntnis der umgebenden Objektstruktur erstellt werden. Weitere Informationen finden Sie unter RelativeSource-Markuperweiterung.

  • TemplateBinding ermöglicht die Verwendung von Eigenschaftswerten in Steuerelementvorlagen, die von den durch das Objektmodell definierten Eigenschaften der Klasse abgeleitet werden, die die Vorlage verwenden werden. Dies bedeutet, dass die Eigenschaft in der Vorlagendefinition auf einen Kontext zugreifen kann, der erst vorhanden ist, wenn die Vorlage angewendet wird. Weitere Informationen finden Sie unter TemplateBinding-Markuperweiterung. Weitere Informationen über die praktische Verwendung von TemplateBinding finden Sie unter Beispiel zum Formatieren mit ControlTemplates.

  • ColorConvertedBitmap unterstützt ein relativ komplexes Bildverarbeitungsszenario. Weitere Informationen finden Sie unter ColorConvertedBitmap-Markuperweiterung.

  • ComponentResourceKey und ThemeDictionary unterstützen Aspekte der Ressourcensuche, insbesondere für Ressourcen und Designs, die in benutzerdefinierten Steuerelementen enthalten sind. Weitere Informationen finden Sie unter ComponentResourceKey-Markuperweiterung, ThemeDictionary-Markuperweiterung oder Übersicht über das Erstellen von Steuerelementen.

*Erweiterungsklassen

Bei den allgemeinen XAML- und WPF-spezifischen Markuperweiterungen wird das Verhalten der einzelnen Markuperweiterungen für einen XAML-Prozessor über eine *Extension-Klasse identifiziert, die von MarkupExtension abgeleitet wird und eine Implementierung der ProvideValue-Methode bereitstellt. Diese für jede Erweiterung verwendete Methode stellt das Objekt bereit, das bei der Auswertung der Markuperweiterung zurückgegeben wird. Das zurückgegebene Objekt wird normalerweise auf Grundlage der verschiedenen Zeichenfolgentoken ausgewertet, die an die Markuperweiterung übergeben werden.

Beispiel: Die StaticResourceExtension-Klasse stellt die Oberflächenimplementierung der tatsächlichen Ressourcensuche bereit, sodass die zugehörige ProvideValue-Implementierung das angeforderte Objekt zurückgibt, wobei die Eingabe dieser Implementierung eine Zeichenfolge ist, die für die Suche nach der Ressource anhand des zugehörigen x:Key verwendet wird. Ein großer Teil dieser Implementierungsdetails ist nicht von Bedeutung, wenn Sie eine vorhandene Markuperweiterung verwenden.

Einige Markuperweiterungen verwenden keine Zeichenfolgentokenargumente. Dies ist darauf zurückzuführen, dass sie einen statischen oder konsistenten Wert zurückgeben, oder darauf, dass der Kontext zum Bestimmen des zurückzugebenden Werts durch einen der mit dem serviceProvider-Parameter übergebenen Dienste verfügbar ist.

Das *Extension-Namensmuster dient der besseren Übersichtlichkeit und Konsistenz. Es ist nicht erforderlich, damit ein XAML-Prozessor diese Klasse als Unterstützung für eine Markuperweiterung identifiziert. Sofern die Codebasis "System.Xaml" enthält und die .NET Framework-XAML-Dienstimplementierung verwendet, müssen alle Elemente, die als XAML-Markuperweiterung erkannt werden sollen, von MarkupExtension abgeleitet werden und eine Konstruktionssyntax unterstützen. WPF definiert Klassen für Markuperweiterungen, die dem *Extension-Benennungsmuster nicht folgen, z. B. Binding. Der Grund hierfür ist normalerweise, dass die Klasse Szenarien unterstützt, die über die reine Unterstützung von Markuperweiterungen hinausgehen. Im Fall von Binding unterstützt diese Klasse zur Laufzeit den Zugriff auf Methoden und Eigenschaften des Objekts. Diese Unterstützung dient für Szenarien, in denen XAML nicht verwendet wird.

Erweiterungsklasse – Interpretation des Initialisierungstexts

Die Zeichenfolgentoken, die auf den Namen der Markuperweiterung folgen und sich innerhalb der Klammern befinden, werden von einem XAML-Prozessor auf eine der folgenden Arten interpretiert:

  • Ein Komma fungiert immer als Trennzeichen einzelner Token.

  • Wenn die einzelnen getrennten Token keine Gleichheitszeichen enthalten, wird jedes Token als Konstruktorargument behandelt. Jeder Konstruktorparameter muss als Typ angegeben werden, der von der Signatur erwartet wird, und die Angabe muss in der von der Signatur erwarteten Reihenfolge erfolgen.

    HinweisHinweis

    Ein XAML-Prozessor muss den Konstruktor aufrufen, der der Argumentanzahl der Anzahl von Paaren entspricht.Wenn Sie eine benutzerdefinierte Markuperweiterung implementieren, dürfen Sie aus diesem Grund nicht mehrere Parameter mit derselben Argumentanzahl bereitstellen.Das Verhalten eines XAML-Prozessors, wenn mehrere Konstruktorpfade der Markuperweiterung mit derselben Parameteranzahl vorhanden sind, ist nicht definiert. Sie sollten jedoch davon ausgehen, dass ein XAML-Prozessor eine Ausnahme auslösen kann, wenn diese Situation in den Typdefinitionen der Markuperweiterung vorliegt.

  • Wenn die einzelnen Token Gleichheitszeichen enthalten, ruft der XAML-Prozessor zuerst den Standardkonstruktor für die Markuperweiterung auf. Dann wird jedes Name=Wert-Paar als in der Markuperweiterung vorhandener Eigenschaftenname und als Wert interpretiert, der der Eigenschaft zuzuweisen ist.

  • Wenn in einer Markuperweiterung ein paralleles Ergebnis zwischen dem Konstruktorverhalten und dem Verhalten der Eigenschafteneinstellung vorliegt, können Sie zwischen den Verhalten wählen. Die Verwendung von Eigenschaft=Wert-Paaren mit mehreren festlegbaren Eigenschaften für Markuperweiterungen ist gängiger, da hierbei ein geringeres Risiko besteht, Konstruktorparameter versehentlich zu vertauschen. (Bei der Angabe von Eigenschaft=Wert-Paaren spielt die Reihenfolge der Eigenschaften keine Rolle). Des Weiteren ist nicht garantiert, dass eine Markuperweiterung einen Konstruktorparameter angibt, der alle festlegbaren Eigenschaften festlegt. Beispiel: Binding ist eine Markuperweiterung mit vielen Eigenschaften, die durch die Erweiterung in der Form Eigenschaft=Wert festlegbar sind, Binding unterstützt jedoch nur zwei Konstruktoren: einen Standardkonstruktor und einen Konstruktor, der einen Anfangspfad festlegt.

  • Ein Komma kann nicht ohne Vorschub als Literalzeichen an eine Markuperweiterung übergeben werden.

Escapesequenzen und Markuperweiterungen

Bei der Attributbehandlung in einem XAML-Prozessor werden geschweifte Klammern als Bezeichner für Markuperweiterungssequenzen verwendet. Falls erforderlich, können Sie geschweifte Klammern als Literalzeichen angeben, indem Sie eine Escapesequenz in Form eines leeren Paars geschweifter Klammern gefolgt von der literalen geschweiften Klammer angeben. Weitere Informationen finden Sie unter {}-Escapesequenz/Markuperweiterung.

Schachtelung von Markuperweiterungen in der XAML-Verwendung

Die Schachtelung mehrerer Markuperweiterungen wird unterstützt, wobei die einzelnen Markuperweiterungen beginnend mit der tiefsten Ebene ausgewertet werden. Betrachten Sie z. B. die folgende Syntax:

  <Setter Property="Background"
    Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" />

Die x:Static-Anweisung wird hier zuerst ausgewertet und gibt eine Zeichenfolge zurück. Diese Zeichenfolge wird dann als Argument für DynamicResource verwendet.

Markuperweiterungen und Eigenschaftenelementsyntax

Bei Verwendung als Objektelement, das in einen Eigenschaftenelementwert geladen wird, ist eine Markuperweiterungsklasse visuell nicht von regulären typgestützten Objekten zu unterscheiden, die in XAML verwendet werden können. In diesem Fall besteht der praktische Unterschied zwischen einem typischen Objektelement und einer Markuperweiterung darin, dass die Markuperweiterung entweder als typisierter Wert ausgewertet oder als Ausdruck verzögert wird. Aus diesem Grund unterscheiden sich die Mechanismen für mögliche Typfehler bei Eigenschaftswerten für die Markuperweiterung. Dies ist mit der Behandlung einer Eigenschaft mit später Bindung in anderen Programmiermodellen vergleichbar. Ein normales Objektelement wird beim Analysieren des XAML hinsichtlich der Typübereinstimmung mit der von ihm festgelegten Zieleigenschaft ausgewertet.

Die meisten Markuperweiterungen würden keinen Inhalt oder weitere Eigenschaftenelementsyntax aufweisen, wenn sie in der Objektelementsyntax in ein Eigenschaftenelement geladen werden. Deshalb würden Sie das Objektelementtag schließen und keine untergeordneten Elemente bereitstellen. Wenn ein Objektelement von einem XAML-Prozessor erkannt wird, wird der Konstruktor für diese Klasse aufgerufen, die das aus dem analysierten Element erstellte Objekt instanziiert. Dies gilt auch für Markuperweiterungsklassen. Wenn Sie die Markuperweiterung in Objektelementsyntax verwenden möchten, müssen Sie einen Standardkonstruktor angeben. Einige vorhandene Markuperweiterungen verfügen über mindestens einen erforderlichen Eigenschaftswert, der für die effektive Initialisierung angegeben werden muss. Wenn dies der Fall ist, wird dieser Eigenschaftswert in der Regel als Eigenschaftenattribut für das Objektelement angegeben. Markuperweiterungen mit erforderlichen Eigenschaften (sowie die Namen dieser Eigenschaften) werden auf den Referenzseiten Sprachfeatures des XAML-Namespace (x:) und WPF-XAML-Erweiterungen aufgeführt. Des Weiteren wird auf den Referenzseiten darauf hingewiesen, wenn Objektelementsyntax oder Attributsyntax von einer Markuperweiterung nicht unterstützt werden. Ein wichtiger Fall ist x:Array-Markuperweiterung, die Attributsyntax nicht unterstützt, da der Inhalt des Arrays innerhalb der Tags als Inhalt angegeben werden muss. Die Arrayinhalte werden als allgemeine Objekte behandelt, sodass kein Standardtypkonverter für das Attribut zulässig ist. Außerdem erfordert x:Array-Markuperweiterung einen type-Parameter.

Siehe auch

Referenz

StaticResource-Markuperweiterung

Bindung als Markuperweiterung

DynamicResource-Markuperweiterung

x:Type-Markuperweiterung

Konzepte

Übersicht über XAML (WPF)

Weitere Ressourcen

Sprachfeatures des XAML-Namespace (x:)

WPF-XAML-Erweiterungen