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 wird das Konzept von Markuperweiterungen für XAML vorgestellt, einschließlich ihrer Syntaxregeln, Zweck und des Klassenobjektmodells, das ihnen zugrunde lieh. Markuperweiterungen sind ein allgemeines Feature der XAML-Sprache und der .NET-Implementierung von XAML-Diensten. In diesem Thema werden speziell Markuperweiterungen für die Verwendung in WPF-XAML erläutert.
XAML-Prozessoren und Markuperweiterungen
Im Allgemeinen kann ein XAML-Parser entweder einen Attributwert als Literalzeichenfolge interpretieren, die in einen Grundtyp konvertiert werden kann, oder es auf irgendeine Art und Art in ein Objekt konvertieren. Ein solches Mittel besteht darin, auf einen Typkonverter zu verweisen; dies ist im Thema TypeConverters und XAML dokumentiert. Es gibt jedoch Szenarien, in denen ein anderes Verhalten erforderlich ist. Beispielsweise kann ein XAML-Prozessor angewiesen werden, dass ein Wert eines Attributs nicht zu einem neuen Objekt im Objektdiagramm führen soll. Stattdessen sollte das Attribut zu einem Objektdiagramm führen, das einen Verweis auf ein bereits erstelltes Objekt in einem anderen Teil des Diagramms oder einem statischen Objekt vorgibt. Ein weiteres Szenario besteht darin, dass ein XAML-Prozessor angewiesen werden kann, eine Syntax zu verwenden, die dem Konstruktor eines Objekts nicht standardmäßige Argumente bereitstellt. Dies sind die Arten von Szenarien, in denen eine Markuperweiterung die Lösung bereitstellen kann.
Grundlegende Markup-Erweiterungssyntax
Eine Markuperweiterung kann implementiert werden, um Werte für Eigenschaften in einer Attributverwendung, Eigenschaften in einer Eigenschaftselementverwendung oder beides bereitzustellen.
Wenn beim Bereitstellen eines Attributwerts die Syntax verwendet wird, die eine Markup-Erweiterungssequenz für einen XAML-Prozessor unterscheidet, ist das Vorhandensein der öffnenden und schließenden geschweiften Klammern ({ und }) entscheidend. Der Typ der Markuperweiterung wird dann durch das String-Token unmittelbar nach der öffnenden geschweiften Klammer identifiziert.
Bei Verwendung in der Eigenschaftselementsyntax ist eine Markuperweiterung visuell mit jedem anderen Element identisch, das zum Bereitstellen eines Eigenschaftselementwerts verwendet wird: eine XAML-Elementdeklaration, die auf die Markuperweiterungsklasse als Element verweist, das in winkeln Klammern (<>) eingeschlossen ist.
XAML-Defined Markup-Erweiterungen
Es gibt mehrere Markuperweiterungen, die nicht spezifisch für die WPF-Implementierung von XAML sind, sondern stattdessen Implementierungen von grundlegenden Funktionen oder Eigenschaften von XAML als Sprache. Diese Markuperweiterungen werden in der System.Xaml-Assembly als Teil der allgemeinen .NET Framework-XAML-Dienste implementiert und befinden sich im XAML-Sprach-XAML-Namespace. Im Hinblick auf die allgemeine Markupverwendung sind diese Markuperweiterungen typischerweise durch das Präfix x:
in der Verwendung identifizierbar. Die MarkupExtension Basisklasse (auch in System.Xaml definiert) stellt das Muster bereit, das alle Markuperweiterungen verwenden sollten, um in XAML-Lesern und XAML-Autoren unterstützt zu werden, einschließlich in WPF-XAML.
x:Type
stellt das Type Objekt für den benannten Typ zur. Diese Funktion wird am häufigsten in Stilen und Vorlagen verwendet. Ausführliche Informationen finden Sie unter "x:Type Markup Extension".x:Static
erzeugt statische Werte. Die Werte stammen aus Werttypcodeentitäten, die nicht direkt den Typ des Werts einer Zieleigenschaft sind, aber für diesen Typ ausgewertet werden können. Ausführliche Informationen finden Sie unter x:Static Markup Extension.x:Null
Gibtnull
als Wert für eine Eigenschaft an und kann entweder für Attribute oder Eigenschaftselementwerte verwendet werden. Ausführliche Informationen finden Sie unter x:Null Markup Extension.x:Array
bietet Unterstützung bei der Erstellung von allgemeinen Arrays in XAML-Syntax, für Fälle, in denen die angebotene Sammlungsunterstützung der WPF-Basiselemente und Steuerungsmodelle bewusst nicht genutzt wird. Ausführliche Informationen finden Sie unter "x:Array Markup Extension".
Hinweis
Das x:
Präfix wird für die typische Zuordnung des XAML-Namespace der grundlegenden Funktionen der XAML-Sprache im Stammelement einer XAML-Datei oder -Produktion verwendet. Beispielsweise initiieren die Visual Studio-Vorlagen für WPF-Anwendungen 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 Standardzuordnung x:
als Mittel zur Identifizierung der Entitäten angenommen, die ein definierter Teil des XAML-Namespace für die XAML-Sprache sind, im Gegensatz zu den WPF-Standardnamespaces oder anderen XAML-Namespaces, die nicht mit einem bestimmten Framework zusammenhängen.
WPF-Specific Markuperweiterungen
Die am häufigsten in der WPF-Programmierung verwendeten Markuperweiterungen sind diejenigen, die Ressourcenverweise (StaticResource
und DynamicResource
) unterstützen, und diejenigen, die die Datenbindung (Binding
) unterstützen.
StaticResource
stellt einen Wert für eine Eigenschaft bereit, indem der Wert einer bereits definierten Ressource ersetzt wird. EineStaticResource
Auswertung erfolgt letztendlich zur XAML-Ladezeit und hat keinen Zugriff auf das Objektdiagramm zur Laufzeit. Ausführliche Informationen finden Sie unter StaticResource-Markuperweiterung.DynamicResource
stellt einen Wert für eine Eigenschaft bereit, indem dieser Wert zurückverzögert wird, um einen Laufzeitverweis auf eine Ressource zu sein. Ein dynamischer Ressourcenverweis erzwingt jedes Mal eine neue Suche, wenn auf eine solche Ressource zugegriffen wird und zur Laufzeit Zugriff auf das Objektdiagramm hat. Um diesen Zugriff zu erhalten, wird das Konzept durch Abhängigkeitseigenschaften im WPF-Eigenschaftensystem und durch ausgewertete Ausdrücke unterstützt. Daher können Sie nur für ein Abhängigkeitseigenschaftsziel verwendenDynamicResource
. Ausführliche Informationen finden Sie unter DynamicResource-Markuperweiterung.Binding
stellt einen datengebundenen Wert für eine Eigenschaft bereit, wobei der Datenkontext verwendet wird, der zur Laufzeit auf das übergeordnete Objekt angewendet wird. Diese Markuperweiterung ist relativ komplex, da sie eine wesentliche Inlinesyntax zum Angeben einer Datenbindung ermöglicht. Ausführliche Informationen finden Sie unter Binding Markup Extension.RelativeSource
stellt Quellinformationen für ein Binding Objekt bereit, das in einem Objektbaum zur Laufzeit verschiedene mögliche Beziehungen navigieren kann. Dies bietet eine spezialisierte Quellenbeschaffung für Bindungen, die in mehrfach verwendbaren Vorlagen erstellt oder im Code ohne vollständige Kenntnis der umgebenden Objektstruktur erstellt werden. Ausführliche Informationen finden Sie unter RelativeSource MarkupExtension.TemplateBinding
ermöglicht es einer Steuerelementvorlage, Werte für vorlagenbasierte Eigenschaften zu verwenden, die aus objektmodelldefinierten Eigenschaften der Klasse stammen, die die Vorlage verwenden wird. Mit anderen Worten, die Eigenschaft innerhalb der Vorlagendefinition kann auf einen Kontext zugreifen, der nur vorhanden ist, nachdem die Vorlage angewendet wurde. Weitere Informationen finden Sie unter TemplateBinding Markup Extension. Weitere Informationen zur praktischen Verwendung vonTemplateBinding
finden Sie unter Beispiel für das Stylen mit ControlTemplates.ColorConvertedBitmap
unterstützt ein relativ erweitertes Imageerstellungsszenario. Weitere Informationen finden Sie unter ColorConvertedBitmap-Markuperweiterung.ComponentResourceKey
undThemeDictionary
unterstützen Aspekte der Ressourcensuche, insbesondere für Ressourcen und Themen, die mit benutzerdefinierten Steuerelementen verpackt sind. Weitere Informationen finden Sie unter ComponentResourceKey Markup Extension, ThemeDictionary Markup Extension oder Control Authoring Overview.
*Erweiterungsklassen
Sowohl für die allgemeine XAML-Sprache als auch für WPF-spezifische Markuperweiterungen wird das Verhalten jeder Markuperweiterung für einen XAML-Prozessor über eine *Extension
Klasse identifiziert, von MarkupExtensionder abgeleitet wird, und stellt eine Implementierung der ProvideValue Methode bereit. Diese Methode für jede Erweiterung stellt das Objekt bereit, das zurückgegeben wird, wenn die Markuperweiterung ausgewertet wird. Das zurückgegebene Objekt wird in der Regel basierend auf den verschiedenen Zeichenfolgentoken ausgewertet, die an die Markuperweiterung übergeben werden.
Die StaticResourceExtension Klasse stellt zum Beispiel die grundlegende Implementierung der tatsächlichen Ressourcensuche bereit, sodass ihre ProvideValue Implementierung das angeforderte Objekt zurückgibt. Dabei ist die Eingabe dieser spezifischen Implementierung eine Zeichenfolge, die verwendet wird, um die Ressource anhand ihrer x:Key
zu ermitteln. Viele dieser Implementierungsdetails sind unwichtig, wenn Sie eine vorhandene Markuperweiterung verwenden.
Einige Markuperweiterungen verwenden keine Zeichenfolgentokenargumente. Dies liegt entweder daran, dass sie einen statischen oder konsistenten Wert zurückgeben oder der Kontext für den zurückgegebenen Wert über einen der dienste verfügbar ist, die über den serviceProvider
Parameter übergeben werden.
Das *Extension
Benennungsmuster dient der Einfachheit und Konsistenz. Es ist nicht erforderlich, damit ein XAML-Prozessor diese Klasse als Unterstützung für eine Markuperweiterung identifiziert. Solange Ihre Codebasis System.Xaml enthält und .NET Framework XAML Services-Implementierungen verwendet, müssen sie nur als XAML-Markuperweiterung erkannt werden, um eine MarkupExtension Konstruktionssyntax abzuleiten und zu unterstützen. WPF definiert markuperweiterungsfähige Klassen, die nicht dem *Extension
-Benennungsmuster folgen, z. B. Binding. In der Regel ist dies der Grund dafür, dass die Klasse Szenarien über reine Markuperweiterungsunterstützung hinaus unterstützt. Im Fall von Binding, diese Klasse unterstützt Laufzeitzugriff auf Methoden und Eigenschaften des Objekts für Szenarien, die nichts mit XAML zu tun haben.
Erweiterungsklasseninterpretation von Initialisierungstext
Die Zeichenfolgentoken, die dem Namen der Markuperweiterung folgen und sich noch in den geschweiften Klammern befinden, werden von einem XAML-Prozessor auf eine der folgenden Arten interpretiert:
Ein Komma stellt immer das Trennzeichen oder Trennzeichen einzelner Token dar.
Wenn die einzelnen getrennten Token keine Gleichheitszeichen enthalten, wird jedes Token als Konstruktorargument behandelt. Jeder Konstruktorparameter muss als typ angegeben werden, der von dieser Signatur erwartet wird, und in der richtigen Reihenfolge, die von dieser Signatur erwartet wird.
Hinweis
Ein XAML-Prozessor muss den Konstruktor aufrufen, der der Argumentanzahl der Anzahl der Paare entspricht. Aus diesem Grund stellen Sie bei der Implementierung einer benutzerdefinierten Markuperweiterung nicht mehrere Konstruktoren mit derselben Argumentanzahl bereit. Das Verhalten eines XAML-Prozessors, wenn mehr als ein Markuperweiterungskonstruktorpfad mit derselben Parameteranzahl vorhanden ist, ist nicht definiert. Sie sollten jedoch davon ausgehen, dass ein XAML-Prozessor eine Ausnahme bei der Verwendung auslösen darf, wenn diese Situation in den Markuperweiterungstypdefinitionen vorhanden ist.
Wenn die einzelnen getrennten Token gleich Zeichen enthalten, ruft ein XAML-Prozessor zuerst den parameterlosen Konstruktor für die Markuperweiterung auf. Anschließend wird jedes Name=Wert-Paar als Eigenschaftsname interpretiert, der in der Markuperweiterung vorhanden ist, und ein Wert, der dieser Eigenschaft zugewiesen werden soll.
Wenn es ein paralleles Ergebnis zwischen dem Konstruktorverhalten und dem Eigenschafteneinstellungsverhalten in einer Markuperweiterung gibt, spielt es keine Rolle, welches Verhalten Sie verwenden. Es wird häufiger verwendet, dieEigenschaftswertpaare
=
für Markuperweiterungen zu verwenden, die mehr als eine festgelegte Eigenschaft aufweisen, wenn nur, weil das Markup absichtlicher wird und Sie weniger wahrscheinlich Konstruktorparameter transponieren. (Wenn Sie Eigenschaft=Wert-Paare angeben, können diese in beliebiger Reihenfolge angegeben werden.) Außerdem gibt es keine Garantie dafür, dass eine Markuperweiterung einen Konstruktorparameter bereitstellt, der jede ihrer festlegbaren Eigenschaften festlegt. Beispielsweise handelt es sich um eine Markuperweiterung mit vielen Eigenschaften, Binding die über die Erweiterung imEigenschaftenwertformular=
festgelegt werden können, aber Binding nur zwei Konstruktoren unterstützt: einen parameterlosen Konstruktor und einen, der einen anfänglichen Pfad festlegt.Ein literales Komma kann nicht ohne Entkommmarkierung an eine Markuperweiterung übergeben werden.
Escape-Sequenzen und Markup-Erweiterungen
Die Attributverarbeitung in einem XAML-Prozessor verwendet die geschweiften Klammern als Indikatoren für eine Markup-Erweiterungssequenz. Es ist auch möglich, bei Bedarf einen literalen geschweiften Klammern-Attributwert zu erzeugen, indem Sie eine Escapesequenz eingeben, die ein leeres geschweiftes Paar gefolgt von der literalen geschweiften Klammer enthält. Siehe {} Escapesequenz – Markuperweiterung.
Verschachtelung von Markuperweiterungen in der Anwendung von XAML
Die Verschachtelung mehrerer Markup-Erweiterungen wird unterstützt, und jede Markup-Erweiterung wird zuerst auf der tiefsten Ebene ausgewertet. Betrachten Sie beispielsweise die folgende Verwendung:
<Setter Property="Background"
Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" />
In dieser Verwendung wird die x:Static
Anweisung zuerst ausgewertet und gibt eine Zeichenfolge zurück. Diese Zeichenfolge wird dann als Argument für DynamicResource
verwendet.
Markuperweiterungen und Eigenschaftselementsyntax
Eine Markuperweiterungsklasse ist visuell nicht von einem typischen typgestützten Objektelement zu unterscheiden, wenn sie als Objektelement verwendet wird, das einen Eigenschaftselementwert ausfüllt und in XAML eingesetzt werden kann. Der praktische Unterschied zwischen einem typischen Objektelement und einer Markuperweiterung besteht darin, dass die Markuperweiterung entweder auf einen typierten Wert ausgewertet oder als Ausdruck zurückgestellt wird. Daher unterscheiden sich die Mechanismen für mögliche Typenfehler von Eigenschaftswerten für die Markuperweiterung, ähnlich wie eine spät gebundene Eigenschaft in anderen Programmiermodellen behandelt wird. Ein gewöhnliches Objektelement wird auf Übereinstimmung des Typs mit der Zieleigenschaft hin ausgewertet, die es beim Parsen von XAML festlegt.
Die meisten Markuperweiterungen, die in der Objektelementsyntax zum Ausfüllen eines Eigenschaftselements verwendet werden, hätten keinen Inhalt oder eine weitere Eigenschaftselementsyntax innerhalb. Daher sollten Sie das Tag des Objektelements schließen und keine untergeordneten Tags bereitstellen. Wenn ein Objektelement von einem XAML-Prozessor gefunden wird, wird der Konstruktor für diese Klasse aufgerufen, der das aus dem analysierten Element erstellte Objekt instanziiert. Eine Markuperweiterungsklasse unterscheidet sich nicht: Wenn Die Markuperweiterung in der Objektelementsyntax verwendet werden soll, müssen Sie einen parameterlosen Konstruktor angeben. Einige vorhandene Markuperweiterungen verfügen über mindestens einen erforderlichen Eigenschaftswert, der für die effektive Initialisierung angegeben werden muss. Wenn ja, wird dieser Eigenschaftswert in der Regel als Eigenschaftsattribut für das Objektelement angegeben. In den Referenzseiten für XAML-Namespaces (x:) Sprachfeatures und WPF-XAML-Erweiterungen, werden Markup-Erweiterungen, die erforderliche Eigenschaften haben (und die Namen der erforderlichen Eigenschaften), besonders hervorgehoben. Referenzseiten geben auch an, ob die Objektelementsyntax oder die Attributsyntax bei bestimmten Markuperweiterungen nicht erlaubt ist. Ein wichtiger Fall ist x:Array Markup Extension, die keine Attributsyntax unterstützen kann, da der Inhalt dieses Arrays innerhalb des Tags als Inhalt angegeben werden muss. Der Arrayinhalt wird als allgemeine Objekte behandelt, daher ist kein Standardtypkonverter für das Attribut machbar. Außerdem erfordert die x:Array-Markuperweiterung einen type
Parameter.
Siehe auch
.NET Desktop feedback