Freigeben über


XAML-Knotenstreamstrukturen und -konzepte

XAML-Reader und XAML-Autoren wie in .NET XAML Services implementiert basieren auf dem Entwurfskonzept eines XAML-Knotenstreams. Der XAML-Knotenstream ist eine Konzeptualisierung einer Gruppe von XAML-Knoten. In dieser Konzeptualisierung durchläuft ein XAML-Prozessor die Struktur der Knotenbeziehungen im XAML-Code einzeln. Zu jedem Zeitpunkt ist nur ein aktueller Datensatz oder eine aktuelle Position in einem geöffneten XAML-Knotenstream vorhanden, und viele Aspekte des API-Berichts sind nur die Informationen, die an dieser Position verfügbar sind. Der aktuelle Knoten in einem XAML-Knotendatenstrom kann als Objekt, Element oder Wert beschrieben werden. Durch die Behandlung von XAML als XAML-Knotendatenstrom können XAML-Leser mit XAML-Autoren kommunizieren und einem Programm das Anzeigen, Interagieren mit oder Ändern des Inhalts eines XAML-Knotendatenstroms während eines Ladepfads oder eines Speicherpfadvorgangs, der XAML umfasst, ermöglichen. Das XAML-Reader- und Writer-API-Design und das KONZEPT des XAML-Knotenstreams ähneln vorherigen zugehörigen Reader- und Writer-Designs und Konzepten wie dem XML-Dokumentobjektmodell (DOM) und den XmlReader- und XmlWriter-Klassen. In diesem Thema werden XAML-Knotenstreamkonzepte erläutert und beschrieben, wie Sie Routinen schreiben können, die mit XAML-Darstellungen auf XAML-Knotenebene interagieren.

Laden von XAML in einen XAML-Reader

Die Basisklasse XamlReader klasse deklariert keine bestimmte Technik zum Laden des anfänglichen XAML in einen XAML-Reader. Stattdessen deklariert und implementiert eine abgeleitete Klasse die Ladetechnik, einschließlich der allgemeinen Merkmale und Einschränkungen der Eingabequelle für XAML. Beispielsweise liest ein XamlObjectReader ein Objektdiagramm ab der Eingabequelle eines einzelnen Objekts, das den Stamm oder die Basis darstellt. Die XamlObjectReader erzeugt dann einen XAML-Knotendatenstrom aus dem Objektdiagramm.

Die prominenteste .NET XAML Services–defined XamlReader-Unterklasse ist XamlXmlReader. XamlXmlReader lädt den ursprünglichen XAML-Code, entweder durch direktes Laden einer Textdatei über einen Datenstrom oder Dateipfad oder indirekt über eine zugehörige Leseklasse wie TextReader. Der XamlReader kann man sich überlegen, wie er die gesamte XAML-Eingabequelle enthält, nachdem sie geladen wurde. Die XamlReader Basis-API ist jedoch so konzipiert, dass der Reader mit einem einzelnen Knoten des XAML-Codes interagiert. Beim ersten Laden ist der erste einzelne Knoten, den Sie treffen, der Stamm des XAML-Codes und dessen Startobjekt.

Das XAML-Knotenstreamkonzept

Wenn Sie mit einem DOM-, Strukturmetapher- oder abfragebasierten Ansatz für den Zugriff auf XML-basierte Technologien vertraut sind, ist eine hilfreiche Möglichkeit, einen XAML-Knotenstream wie folgt zu konzeptualisieren. Stellen Sie sich vor, dass es sich bei dem geladenen XAML-Code um ein DOM oder eine Struktur handelt, in der alle möglichen Knoten vollständig erweitert und dann linear dargestellt werden. Während Sie die Knoten durchlaufen, durchlaufen Sie möglicherweise "in" oder "out" von Ebenen, die für ein DOM relevant wären, aber der XAML-Knotendatenstrom verfolgt nicht explizit, da diese Ebenenkonzepte für einen Knotendatenstrom nicht relevant sind. Der Knotendatenstrom hat eine "aktuelle" Position, aber es sei denn, Sie haben andere Teile des Datenstroms selbst als Verweise gespeichert, jeder Aspekt des Knotendatenstroms, der nicht die aktuelle Knotenposition ist, nicht sichtbar.

Das XAML-Knotenstream-Konzept hat den bemerkenswerten Vorteil, dass Sie beim Durchlaufen des gesamten Knotendatenstroms sicher sind, dass Sie die gesamte XAML-Darstellung verarbeitet haben. Sie müssen sich keine Sorgen machen, dass eine Abfrage, ein DOM-Vorgang oder ein anderer nichtlinearer Ansatz zur Verarbeitung von Informationen einen Teil der vollständigen XAML-Darstellung verpasst hat. Aus diesem Grund ist die XAML-Knotenstreamdarstellung ideal für die Verbindung von XAML-Lesern und XAML-Autoren sowie für die Bereitstellung eines Systems, in dem Sie einen eigenen Prozess einfügen können, der zwischen den Lese- und Schreibphasen eines XAML-Verarbeitungsvorgangs fungiert. In vielen Fällen wird die Sortierung von Knoten im XAML-Knotendatenstrom von XAML-Lesern absichtlich optimiert oder neu angeordnet, anstatt wie die Reihenfolge im Quelltext, binären oder Objektdiagramm angezeigt werden kann. Dieses Verhalten soll eine XAML-Verarbeitungsarchitektur erzwingen, wobei XAML-Autoren niemals an einer Position sind, an der sie im Knotendatenstrom "zurück" wechseln müssen. Im Idealfall sollten alle XAML-Schreibvorgänge basierend auf dem Schemakontext und der aktuellen Position des Knotendatenstroms handeln können.

Eine einfache Leseknotenschleife

Eine grundlegende Leseknotenschleife zum Untersuchen eines XAML-Knotenstreams besteht aus den folgenden Konzepten. Für Knotenschleifen, wie in diesem Thema erläutert, gehen Sie davon aus, dass Sie eine textbasierte, lesbare XAML-Datei mit XamlXmlReaderlesen. Die Links in diesem Abschnitt beziehen sich auf die bestimmte XAML-Knotenschleifen-API, die von XamlXmlReaderimplementiert wird.

  • Stellen Sie sicher, dass Sie sich nicht am Ende des XAML-Knotendatenstroms befinden (überprüfen Sie IsEof, oder verwenden Sie den Read Rückgabewert). Wenn Sie sich am Ende des Datenstroms befinden, gibt es keinen aktuellen Knoten, und Sie sollten den Vorgang beenden.

  • Überprüfen Sie, welchen Knotentyp der XAML-Knotendatenstrom derzeit verfügbar macht, indem Sie NodeTypeaufrufen.

  • Wenn Sie über einen zugeordneten XAML-Objektschreiber verfügen, der direkt verbunden ist, rufen Sie in der Regel WriteNode an diesem Punkt auf.

  • Rufen Sie basierend darauf, welche XamlNodeType als aktueller Knoten oder aktueller Datensatz gemeldet wird, einen der folgenden Aufrufe, um Informationen zu den Knoteninhalten zu erhalten:

    • Rufen Sie für eine NodeType von StartMember oder EndMemberMember auf, um XamlMember Informationen zu einem Mitglied abzurufen. Das Element kann eine XamlDirectivesein und somit nicht unbedingt ein herkömmliches typdefiniertes Element des vorherigen Objekts sein. Beispielsweise wird x:Name auf ein Objekt angewendet als XAML-Element angezeigt, bei dem IsDirective wahr ist und der Name des Elements Nameist, mit anderen Eigenschaften, die angeben, dass diese Direktive unter dem XAML-Sprach-XAML-Namespace liegt.

    • Rufen Sie für eine NodeType von StartObject oder EndObjectType auf, um XamlType Informationen zu einem Objekt abzurufen.

    • Rufen Sie für eine NodeType von ValueValueauf. Ein Knoten ist nur dann ein Wert, wenn es sich um den einfachsten Ausdruck eines Werts für ein Element oder den Initialisierungstext für ein Objekt handelt (Sie sollten jedoch das Typkonvertierungsverhalten beachten, wie in einem bevorstehenden Abschnitt dieses Themas dokumentiert).

    • Rufen Sie für eine NodeType von NamespaceDeclarationNamespace auf, um Namespaceinformationen für einen Namespaceknoten abzurufen.

  • Rufen Sie Read auf, um den XAML-Reader zum nächsten Knoten im XAML-Knotenstream zu wechseln, und wiederholen Sie die Schritte erneut.

Der von .NET XAML Services-XAML-Readern bereitgestellte XAML-Knotenstream bietet immer eine vollständige, tiefe Traversal aller möglichen Knoten. Typische Flusssteuerungstechniken für eine XAML-Knotenschleife umfassen das Definieren eines Textkörpers innerhalb while (reader.Read())und das Einschalten NodeType an jedem Knotenpunkt in der Knotenschleife.

Wenn sich der Knotendatenstrom am Ende der Datei befindet, ist der aktuelle Knoten null.

Die einfachste Schleife, die einen Reader und Writer verwendet, ähnelt dem folgenden Beispiel.

XamlXmlReader xxr = new XamlXmlReader(new StringReader(xamlStringToLoad));
//where xamlStringToLoad is a string of well formed XAML
XamlObjectWriter xow = new XamlObjectWriter(xxr.SchemaContext);
while (xxr.Read()) {
  xow.WriteNode(xxr);
}

Dieses grundlegende Beispiel für eine XAML-Knotenschleife für den Ladepfad verbindet transparent den XAML-Reader und XAML-Writer und führt nichts anderes aus, als wenn Sie XamlServices.Parseverwendet haben. Diese grundlegende Struktur wird dann jedoch erweitert, um sie auf Ihr Lese- oder Schreibszenario anzuwenden. Einige mögliche Szenarien sind wie folgt:

  • Schalten Sie NodeTypeein. Führen Sie unterschiedliche Aktionen aus, je nachdem, welcher Knotentyp gelesen wird.

  • Rufen Sie WriteNode in allen Fällen nicht auf. Rufen Sie in einigen NodeType Fällen nur WriteNode auf.

  • Analysieren Sie innerhalb der Logik für einen bestimmten Knotentyp die Besonderheiten dieses Knotens, und reagieren Sie darauf. Sie können beispielsweise nur Objekte schreiben, die aus einem bestimmten XAML-Namespace stammen, und dann objekte ablegen oder zurückstellen, die nicht aus diesem XAML-Namespace stammen. Sie können auch alle XAML-Direktiven ablegen oder anderweitig verarbeiten, die ihr XAML-System im Rahmen der Memberverarbeitung nicht unterstützt.

  • Definieren Sie eine benutzerdefinierte XamlObjectWriter, die Write* Methoden außer Kraft setzt und möglicherweise eine Typzuordnung durchführt, die den XAML-Schemakontext umgeht.

  • Erstellen Sie die XamlXmlReader, um einen nicht standardmäßigen XAML-Schemakontext zu verwenden, sodass benutzerdefinierte Unterschiede im XAML-Verhalten sowohl vom Leser als auch vom Writer verwendet werden.

Zugreifen auf XAML über das Knotenschleifenkonzept hinaus

Es gibt potenziell andere Möglichkeiten, mit einer anderen XAML-Darstellung als einer XAML-Knotenschleife zu arbeiten. Beispielsweise könnte ein XAML-Reader vorhanden sein, der einen indizierten Knoten lesen kann oder insbesondere direkt über x:Name, durch x:Uidoder über andere Bezeichner auf Knoten zugreift. .NET XAML Services stellt keine vollständige Implementierung bereit, sondern stellt ein vorgeschlagenes Muster über Dienste und Supporttypen bereit. Weitere Informationen finden Sie unter IXamlIndexingReader und XamlNodeList.

Arbeiten mit dem aktuellen Knoten

Die meisten Szenarien, in denen eine XAML-Knotenschleife verwendet wird, lesen nicht nur die Knoten. Die meisten Szenarien verarbeiten aktuelle Knoten und übergeben jeden Knoten einzeln an eine Implementierung von XamlWriter.

Im typischen Ladepfadszenario erzeugt ein XamlXmlReader einen XAML-Knotendatenstrom; die XAML-Knoten werden gemäß Ihrer Logik und ihrem XAML-Schemakontext verarbeitet; und die Knoten werden an eine XamlObjectWriterübergeben. Anschließend integrieren Sie das resultierende Objektdiagramm in Ihre Anwendung oder das Framework.

In einem typischen Speicherpfadszenario liest ein XamlObjectReader das Objektdiagramm, einzelne XAML-Knoten werden verarbeitet, und ein XamlXmlWriter gibt das serialisierte Ergebnis als XAML-Textdatei aus. Der Schlüssel besteht darin, dass sowohl Pfade als auch Szenarien das Gleichzeitige Arbeiten mit genau einem XAML-Knoten umfassen, und die XAML-Knoten stehen für die Behandlung auf standardisierte Weise zur Verfügung, die vom XAML-Typsystem und the.NET XAML-Dienste-APIs definiert wird.

Frames und Bereich

Eine XAML-Knotenschleife durchläuft einen XAML-Knotendatenstrom linear. Der Knotendatenstrom durchläuft objekte, in Elemente, die andere Objekte enthalten usw. Es ist häufig hilfreich, den Bereich innerhalb des XAML-Knotendatenstroms nachzuverfolgen, indem ein Frame- und Stapelkonzept implementiert wird. Dies gilt insbesondere, wenn Sie den Knotendatenstrom aktiv anpassen, während Sie sich darin befinden. Die Frame- und Stack-Unterstützung, die Sie als Teil der Knotenschleifenlogik implementieren, kann StartObject (oder GetObject) und EndObject Bereiche zählen, während Sie in eine XAML-Knotenstruktur absteigen, wenn die Struktur aus DOM-Perspektive betrachtet wird.

Durchlaufen und Eingeben von Objektknoten

Der erste Knoten in einem Knotendatenstrom, wenn er von einem XAML-Reader geöffnet wird, ist der Startobjektknoten des Stammobjekts. Standardmäßig ist dieses Objekt immer ein einzelner Objektknoten und hat keine Peers. In jedem realen XAML-Beispiel wird das Stammobjekt definiert, um eine oder mehrere Eigenschaften zu haben, die mehr Objekte enthalten, und diese Eigenschaften weisen Memberknoten auf. Die Memberknoten verfügen dann über einen oder mehrere Objektknoten oder können stattdessen in einem Wertknoten beendet werden. Das Stammobjekt definiert in der Regel XAML-NameScopes, die syntaktisch als Attribute im XAML-Textmarkup zugewiesen werden, aber einem Namescope Knotentyp in der XAML-Knotenstreamdarstellung zugeordnet sind.

Betrachten Sie das folgende XAML-Beispiel (dies ist beliebiges XAML, nicht durch vorhandene Typen in .NET gesichert). Gehen Sie davon aus, dass FavorCollection in diesem Objektmodell List<T> von Favorist, Balloon und NoiseMakerFavorzuweisen können, wird die Balloon.Color-Eigenschaft durch ein Color Objekt unterstützt, das der Definition von Farben als bekannte Farbnamen ähnelt, und Color einen Typkonverter für die Attributsyntax unterstützt.

XAML-Markup Resultierender XAML-Knotendatenstrom
<Party Namespace Knoten für Party
xmlns="PartyXamlNamespace"> StartObject Knoten für Party
<Party.Favors> StartMember Knoten für Party.Favors
StartObject Knoten für implizite FavorCollection
StartMember Knoten für implizite FavorCollection Items-Eigenschaft.
<Balloon StartObject Knoten für Balloon
Color="Red" StartMember Knoten für Color

Value Knoten für die Attributwertzeichenfolge "Red"

EndMember für Color
HasHelium="True" StartMember Knoten für HasHelium

Value Knoten für die Attributwertzeichenfolge "True"

EndMember für HasHelium
> EndObject für Balloon
<NoiseMaker>Loudest</NoiseMaker> StartObject Knoten für NoiseMaker

StartMember Knoten für _Initialization

Value Knoten für die Initialisierungswertzeichenfolge "Loudest"

EndMember Knoten für _Initialization

EndObject für NoiseMaker
EndMember Knoten für implizite FavorCollection Items-Eigenschaft.
EndObject Knoten für implizite FavorCollection
</Party.Favors> EndMember für Favors
</Party> EndObject für Party

Im XAML-Knotendatenstrom können Sie sich auf das folgende Verhalten verlassen:

  • Wenn ein Namespace Knoten vorhanden ist, wird er dem Datenstrom unmittelbar vor dem StartObject hinzugefügt, der den XAML-Namespace mit xmlnsdeklariert hat. Sehen Sie sich die vorherige Tabelle mit dem XAML- und Beispielknotendatenstrom erneut an. Beachten Sie, wie die StartObject und Namespace Knoten im Vergleich zu ihren Deklarationspositionen im Textmarkup transponiert werden scheinen. Dies ist repräsentativ für das Verhalten, bei dem die Namespaceknoten immer vor dem Knoten angezeigt werden, auf den sie im Knotenstream angewendet werden. Der Zweck dieses Designs besteht darin, dass die Namespaceinformationen für Objektautoren von entscheidender Bedeutung sind und bekannt sein müssen, bevor der Objektschreiber versucht, die Typzuordnung durchzuführen oder das Objekt anderweitig zu verarbeiten. Durch das Platzieren der XAML-Namespaceinformationen vor dem Anwendungsumfang im Datenstrom ist es einfacher, den Knotendatenstrom in seiner dargestellten Reihenfolge immer zu verarbeiten.

  • Aufgrund der vorstehenden Überlegungen ist es ein oder mehrere Namespace Knoten, die Sie zuerst in den meisten realen Markupfällen lesen, wenn Sie Knoten von Anfang an durchlaufen, nicht die StartObject des Stamms.

  • Auf einen StartObject Knoten kann StartMember, Valueoder eine sofortige EndObjectfolgen. Es wird nie sofort von einem anderen StartObjectgefolgt.

  • Auf eine StartMember kann ein StartObject, Valueoder eine sofortige EndMemberfolgen. Es kann von GetObjectgefolgt werden, für Elemente, bei denen der Wert von einem vorhandenen Wert des übergeordneten Objekts stammen soll, anstatt von einer StartObject, die einen neuen Wert instanziieren würde. Es kann auch von einem Namespace Knoten gefolgt werden, der für eine bevorstehende StartObjectgilt. Es wird nie sofort von einem anderen StartMembergefolgt.

  • Ein Value Knoten stellt den Wert selbst dar; es gibt keinen "EndValue". Es kann nur von einer EndMembergefolgt werden.

    • XAML-Initialisierungstext des Objekts, wie es durch die Konstruktion verwendet werden kann, führt nicht zu einer Object-Value Struktur. Stattdessen wird ein dedizierter Memberknoten für ein Mitglied mit dem Namen _Initialization erstellt. und dieser Memberknoten enthält die Initialisierungswertzeichenfolge. Wenn es vorhanden ist, ist _Initialization immer der erste StartMember. _Initialization können in einigen XAML-Dienstdarstellungen mit dem XAML-Sprach-XAML-NameScope qualifiziert werden, um zu verdeutlichen, dass _Initialization keine definierte Eigenschaft in Sicherungstypen ist.

    • Eine Member-Value Kombination stellt eine Attributeinstellung des Werts dar. Möglicherweise ist ein Wertkonverter an der Verarbeitung dieses Werts beteiligt, und der Wert ist eine einfache Zeichenfolge. Dies wird jedoch erst ausgewertet, wenn ein XAML-Objektschreiber diesen Knotendatenstrom verarbeitet. Der XAML-Objektschreiber verfügt über den erforderlichen XAML-Schemakontext, die Typsystemzuordnung und andere Unterstützung für Wertkonvertierungen.

  • Auf einen EndMember Knoten kann ein StartMember Knoten für ein nachfolgendes Mitglied oder einen EndObject Knoten für den Memberbesitzer folgen.

  • Auf einen EndObject Knoten kann ein EndMember Knoten folgen. Sie kann auch von einem StartObject Knoten für Fälle gefolgt werden, in denen die Objekte Peers in den Elementen einer Auflistung sind. Oder es kann von einem Namespace Knoten gefolgt werden, der für eine bevorstehende StartObjectgilt.

    • Für den eindeutigen Fall, den gesamten Knotendatenstrom zu schließen, wird der EndObject des Stamms nicht gefolgt; der Reader ist jetzt end-of-file, und Read gibt falsezurück.

Wertkonverter und der XAML-Knotenstream

Ein Wertkonverter ist ein allgemeiner Begriff für eine Markuperweiterung, einen Typkonverter (einschließlich Wert serialisierer) oder eine andere dedizierte Klasse, die über das XAML-Typsystem als Wertkonverter gemeldet wird. Im XAML-Knotendatenstrom weisen eine Typkonverterverwendung und eine Markuperweiterungsverwendung sehr unterschiedliche Darstellungen auf.

Typkonverter im XAML-Knotenstream

Ein Attributsatz, der letztendlich zu einer Typkonverterverwendung führt, wird im XAML-Knotendatenstrom als Wert eines Elements gemeldet. Der XAML-Knotendatenstrom versucht nicht, ein Typkonverterinstanzobjekt zu erstellen und den Wert an ihn zu übergeben. Für die Verwendung der Konvertierungsimplementierung eines Typkonverters ist das Aufrufen des XAML-Schemakontexts und die Verwendung für die Typzuordnung erforderlich. Auch die Bestimmung, welche Typkonverterklasse für die Verarbeitung des Werts verwendet werden soll, erfordert indirekt den XAML-Schemakontext. Wenn Sie den standardmäßigen XAML-Schemakontext verwenden, stehen diese Informationen aus dem XAML-Typsystem zur Verfügung. Wenn Sie die Typkonverterklasseninformationen auf der EBENE des XAML-Knotenstreams benötigen, bevor Sie eine Verbindung mit einem XAML-Writer herstellen, können Sie sie aus den XamlMember Informationen des festzulegenden Elements abrufen. Andernfalls sollte die Typkonvertereingabe im XAML-Knotendatenstrom als einfacher Wert beibehalten werden, bis der rest der Vorgänge, für die das Typzuordnungssystem und der XAML-Schemakontext erforderlich sind, ausgeführt werden, z. B. die Objekterstellung durch einen XAML-Objektschreiber.

Betrachten Sie beispielsweise die folgende Klassendefinitionsgliederung und XAML-Verwendung dafür:

public class BoardSizeConverter : TypeConverter {
  //converts from string to an int[2] by splitting on an "x" char
}
public class GameBoard {
  [TypeConverter(typeof(BoardSizeConverter))]
  public int[] BoardSize; //2x2 array, initialization not shown
}
<GameBoard BoardSize="8x8"/>

Eine Textdarstellung des XAML-Knotendatenstroms für diese Verwendung kann wie folgt ausgedrückt werden:

StartObject mit XamlType, die GameBoard

StartMember mit XamlMember, die BoardSize

Value Knoten mit Textzeichenfolge "8x8"

EndMember übereinstimmungen BoardSize

EndObject übereinstimmungen GameBoard

Beachten Sie, dass in diesem Knotenstream keine Typkonverterinstanz vorhanden ist. Sie können jedoch Typkonverterinformationen abrufen, indem Sie XamlMember.TypeConverter für die XamlMember für BoardSizeaufrufen. Wenn Sie über einen gültigen XAML-Schemakontext verfügen, können Sie die Konvertermethoden auch aufrufen, indem Sie eine Instanz von ConverterInstanceabrufen.

Markuperweiterungen im XAML-Knotenstream

Eine Markuperweiterungsverwendung wird im XAML-Knotenstream als Objektknoten innerhalb eines Elements gemeldet, wobei das Objekt eine Markuperweiterungsinstanz darstellt. Daher wird eine Markuperweiterungsverwendung in der Knotendatenstromdarstellung expliziter dargestellt, als eine Typkonverterverwendung ist, und enthält weitere Informationen. XamlMember Informationen konnten Ihnen nichts über die Markuperweiterung gesagt haben, da die Verwendung situational ist und in jedem möglichen Markupfall variiert; es ist nicht dediziert und implizit pro Typ oder Element wie bei Typkonvertern.

Die Knotendatenstromdarstellung von Markuperweiterungen als Objektknoten ist der Fall, auch wenn die Verwendung der Markuperweiterung in Attributform im XAML-Textmarkup vorgenommen wurde (was häufig der Fall ist). Markuperweiterungsverwendungen, die ein explizites Objektelementformular verwendet haben, werden auf die gleiche Weise behandelt.

Innerhalb eines Markuperweiterungsobjektknotens können Elemente dieser Markuperweiterung vorhanden sein. Die XAML-Knotenstreamdarstellung behält die Verwendung dieser Markuperweiterung bei, unabhängig davon, ob es sich um eine Positionsparameterverwendung oder eine Verwendung mit expliziten benannten Parametern handelt.

Bei einer Positionsparameterverwendung enthält der XAML-Knotendatenstrom eine sprachdefinierte XAML-Eigenschaft _PositionalParameters, die die Verwendung aufzeichnet. Diese Eigenschaft ist eine generische List<T> mit Object Einschränkung. Die Einschränkung ist Objekt und keine Zeichenfolge, da eine verwendung von positionsbezogenen Parametern darin geschachtelte Markuperweiterungsverwendungen enthalten könnte. Um auf die Positionsparameter aus der Verwendung zuzugreifen, können Sie die Liste durchlaufen und die Indexer für einzelne Listenwerte verwenden.

Bei einer benannten Parameterverwendung wird jeder benannte Parameter als Memberknoten dieses Namens im Knotendatenstrom dargestellt. Die Memberwerte sind nicht unbedingt Zeichenfolgen, da eine geschachtelte Markuperweiterungsverwendung vorhanden sein könnte.

ProvideValue aus der Markuperweiterung wird noch nicht aufgerufen. Es wird jedoch aufgerufen, wenn Sie einen XAML-Reader und EINEN XAML-Writer verbinden, damit WriteEndObject beim Untersuchen im Knotendatenstrom auf dem Markuperweiterungsknoten aufgerufen wird. Aus diesem Grund benötigen Sie in der Regel den gleichen XAML-Schemakontext, der verwendet werden würde, um das Objektdiagramm im Ladepfad zu bilden. Andernfalls können ProvideValue aus jeder Markuperweiterung Ausnahmen auslösen, da sie keine erwarteten Dienste zur Verfügung hat.

XAML- und XML-Language-Defined-Elemente im XAML-Knotenstream

Bestimmte Member werden aufgrund von Interpretationen und Konventionen eines XAML-Readers in einen XAML-Knotendatenstrom eingeführt, anstatt durch eine explizite XamlMember Nachschlage- oder Konstruktion. Häufig sind diese Member XAML-Direktiven. In einigen Fällen handelt es sich um das Lesen des XAML-Codes, das die Direktive in den XAML-Knotenstream einführt. Mit anderen Worten, der ursprüngliche Eingabe-XAML-Text hat die Memberdirektive nicht explizit angegeben, aber der XAML-Reader fügt die Direktive ein, um eine strukturelle XAML-Konvention zu erfüllen und Informationen im XAML-Knotenstream zu melden, bevor diese Informationen verloren gehen.

In der folgenden Liste werden alle Fälle aufgeführt, in denen erwartet wird, dass ein XAML-Reader einen XAML-Direktive-Memberknoten einführen und wie dieser Memberknoten in .NET XAML Services-Implementierungen identifiziert wird.

  • Initialisierungstext für einen Objektknoten: Der Name dieses Memberknotens ist _Initialization, stellt sie eine XAML-Direktive dar und wird im XAML-Sprach-XAML-Namespace definiert. Sie können eine statische Entität dafür aus Initializationabrufen.

  • Positionsparameter für eine Markuperweiterung: Der Name dieses Memberknotens ist _PositionalParametersund wird im XAML-Sprach-XAML-Namespace definiert. Sie enthält immer eine generische Liste von Objekten, von denen jeder ein Positionsparameter ist, der durch die Aufteilung auf das , Trennzeichen getrennt ist, wie im Eingabe-XAML angegeben. Sie können eine statische Entität für die Positionparameterdirektive aus PositionalParametersabrufen.

  • Unbekannter Inhalt: Der Name dieses Memberknotens ist _UnknownContent. Streng genommen handelt es sich um eine XamlDirective, die im XAML-Sprach-XAML-Namespace definiert ist. Diese Direktive wird als Sentinel für Fälle verwendet, in denen ein XAML-Objektelement Inhalte im XAML-Quell-XAML enthält, aber keine Inhaltseigenschaft unter dem derzeit verfügbaren XAML-Schemakontext bestimmt werden kann. Sie können diesen Fall in einem XAML-Knotendatenstrom erkennen, indem Sie nach Elementen mit dem Namen _UnknownContentsuchen. Wenn in einem XAML-Knotendatenstrom für den Ladepfad keine andere Aktion ausgeführt wird, wird die standardeinstellung XamlObjectWriter auf versuchten WriteEndObject ausgelöst, wenn das element _UnknownContent in einem objekt gefunden wird. Der StandardXamlXmlWriter wird nicht ausgelöst und behandelt das Element als implizit. Sie können eine statische Entität für _UnknownContent aus UnknownContentabrufen.

  • Collection-Eigenschaft einer Auflistung: Obwohl der zugrunde gehende CLR-Typ einer Sammlungsklasse, die für XAML verwendet wird, normalerweise über eine dedizierte benannte Eigenschaft verfügt, die die Sammlungselemente enthält, ist diese Eigenschaft vor der Sicherungstypauflösung nicht bekannt. Stattdessen führt der XAML-Knotendatenstrom einen Items Platzhalter als Element des XAML-Typs der Auflistung ein. In der .NET XAML Services-Implementierung wird der Name dieser Direktive oder dieses Mitglieds im Knotendatenstrom _Items. Eine Konstante für diese Direktive kann aus Itemsabgerufen werden.

    Beachten Sie, dass ein XAML-Knotendatenstrom möglicherweise eine Items-Eigenschaft mit Elementen enthält, die basierend auf der Zugrundelegungstypauflösung und dem XAML-Schemakontext nicht analysiert werden können. Zum Beispiel

  • XML-definierten Member: Die XML-definierten xml:base, xml:lang und xml:space Member werden als XAML-Direktiven mit dem Namen base, langund space in .NET XAML Services-Implementierungen gemeldet. Der Namespace für diese ist der XML-Namespace http://www.w3.org/XML/1998/namespace. Konstanten für jede dieser Konstanten können aus XamlLanguageabgerufen werden.

Knotenreihenfolge

In einigen Fällen ändert XamlXmlReader die Reihenfolge der XAML-Knoten im XAML-Knotendatenstrom und die Reihenfolge, in der die Knoten angezeigt werden, wenn sie im Markup angezeigt werden oder als XML verarbeitet werden. Dies geschieht, um die Knoten so zu ordnen, dass ein XamlObjectWriter den Knotendatenstrom vorwärts verarbeiten kann. In .NET XAML Services ordnet der XAML-Reader Knoten neu an, anstatt diese Aufgabe dem XAML-Writer zu überlassen, als Leistungsoptimierung für XAML-Objektschreiber-Consumer des Knotendatenstroms.

Bestimmte Direktiven sollen speziell weitere Informationen für die Erstellung eines Objekts aus einem Objektelement bereitstellen. Diese Richtlinien sind: Initialization, PositionalParameters, TypeArguments, FactoryMethod, Arguments. .NET XAML Services-XAML-Reader versuchen, diese Direktiven als erste Member im Knotendatenstrom nach dem StartObjecteines Objekts zu platzieren, aus Gründen, die im nächsten Abschnitt erläutert werden.

XamlObjectWriter-Verhalten und Knotenreihenfolge

StartObject einer XamlObjectWriter ist nicht unbedingt ein Signal für den XAML-Objektschreiber, die Objektinstanz sofort zu konstruieren. XAML enthält mehrere Sprachfeatures, die es ermöglichen, ein Objekt mit zusätzlicher Eingabe zu initialisieren, und sich nicht vollständig auf das Aufrufen eines parameterlosen Konstruktors zu verlassen, um das anfängliche Objekt zu erzeugen, und nur dann Eigenschaften festlegen. Zu diesen Features gehören: XamlDeferLoadAttribute; Initialisierungstext; x:TypeArguments; Positionsparameter einer Markuperweiterung; Factorymethoden und zugeordnete x:Arguments Knoten (XAML 2009). In jedem dieser Fälle wird die eigentliche Objektkonstruktion verzögert, und da der Knotendatenstrom neu angeordnet ist, kann der XAML-Objektschreiber auf ein Verhalten angewiesen werden, das die Instanz tatsächlich erstellt, wenn ein Startelement auftritt, das nicht speziell eine Konstruktionsdirektive für diesen Objekttyp ist.

GetObject

GetObject stellt einen XAML-Knoten dar, bei dem anstatt ein neues Objekt zu erstellen, sollte ein XAML-Objektschreiber stattdessen den Wert der enthaltenden Eigenschaft des Objekts abrufen. Ein typischer Fall, in dem ein GetObject Knoten in einem XAML-Knotendatenstrom für ein Auflistungsobjekt oder ein Wörterbuchobjekt auftritt, wenn die enthaltende Eigenschaft im Objektmodell des Sicherungstyps absichtlich schreibgeschützt ist. In diesem Szenario wird die Auflistung oder das Wörterbuch häufig durch die Initialisierungslogik eines eigenen Typs erstellt und initialisiert (in der Regel leer).

Siehe auch