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.
Ein XAML-NameScope speichert Beziehungen zwischen den XAML-definierten Namen von Objekten und deren Instanzentsprechungen. Dieses Konzept ähnelt der breiteren Bedeutung des Begriffs "NameScope" in anderen Programmiersprachen und -technologien.
Definition von XAML-Namenbereichen
Mit Namen in XAML-Namenbereichen kann der Benutzercode auf die Objekte verweisen, die ursprünglich in XAML deklariert wurden. Das interne Ergebnis der XAML-Analyse besteht darin, dass die Laufzeit einen Satz von Objekten erstellt, die einige oder alle Beziehungen beibehalten, die diese Objekte in den XAML-Deklarationen hatten. Diese Beziehungen werden als bestimmte Objekteigenschaften der erstellten Objekte beibehalten oder für Hilfsmethoden in den Programmiermodell-APIs verfügbar gemacht.
Die typischste Verwendung eines Namens in einem XAML-NameScope ist ein direkter Verweis auf eine Objektinstanz, die durch den Markupkompilierungsdurchlauf als Projektbuildaktion aktiviert wird, kombiniert mit einer generierten InitializeComponent-Methode in den partiellen Klassenvorlagen.
Sie können auch die Hilfsmethode FindName zur Laufzeit verwenden, um einen Verweis auf Objekte zurückzugeben, die mit einem Namen im XAML-Markup definiert wurden.
Weitere Informationen zu Buildaktionen und XAML
Technisch gesehen durchläuft der XAML-Code selbst einen Markup-Compiler-Durchlauf gleichzeitig wie der XAML-Code und die partielle Klasse, die er für Code-Behind definiert, zusammen kompiliert wird. Jedes Objektelement mit einem im Markup definierten Attribut "Name" oder " x:Name" generiert ein internes Feld mit einem Namen, der dem XAML-Namen entspricht. Dieses Feld ist zunächst leer. Anschließend generiert die Klasse eine InitializeComponent-Methode , die nur aufgerufen wird, nachdem der gesamte XAML-Code geladen wurde. Innerhalb der InitializeComponent-Logik wird jedes interne Feld dann mit dem FindName-Rückgabewert für die entsprechende Namenszeichenfolge aufgefüllt. Sie können diese Infrastruktur selbst beobachten, indem Sie nach der Kompilierung die dateien ".g" (generiert) betrachten, die für jede XAML-Seite im Unterordner "/obj" eines Windows-Runtime-App-Projekts erstellt werden. Sie können die Felder und die InitializeComponent-Methode auch als Mitglieder der resultierenden Assemblies sehen, wenn Sie Reflection verwenden oder deren Schnittstellensprache auf andere Weise untersuchen.
Hinweis
Speziell für Visual C++-Komponentenerweiterungen (C++/CX)-Apps wird für das Stammelement einer XAML-Datei kein Sicherungsfeld für einen x:Name-Verweis erstellt. Wenn Sie auf das Stammobjekt aus C++/CX-Code-Behind verweisen müssen, verwenden Sie andere APIs oder Baumdurchlauf. Sie können beispielsweise FindName für ein bekanntes benanntes untergeordnetes Element aufrufen und dann "Parent" aufrufen.
Erstellen von Objekten zur Laufzeit mit XamlReader.Load
XAML kann auch als Zeichenfolgeneingabe für die XamlReader.Load-Methode verwendet werden, die analog zum anfänglichen XAML-Quellanalysevorgang fungiert. XamlReader.Load erstellt zur Laufzeit einen neuen, getrennten Objektbaum. Der getrennte Baum kann dann an einem Punkt am Hauptobjektbaum angeschlossen werden. Sie müssen die von Ihnen erstellte Objektstruktur explizit verbinden, entweder indem Sie sie einer Sammlung von Inhaltseigenschaften wie Children hinzufügen oder eine andere Eigenschaft festlegen, die einen Objektwert erfordert (z. B. indem Sie einen neuen ImageBrush für eine Füllungseigenschaft laden).
XAML-NameScope-Auswirkungen von XamlReader.Load
Der vorläufige XAML-NameScope, der von der neuen Objektstruktur definiert wird, die von XamlReader.Load erstellt wurde, wertet alle definierten Namen im bereitgestellten XAML-Code aus, um eindeutig zu sein. Wenn Namen im bereitgestellten XAML-Code zu diesem Zeitpunkt nicht intern eindeutig sind, löst XamlReader.Load eine Ausnahme aus. Die getrennte Objektstruktur versucht nicht, ihren XAML-NameScope mit dem XAML-NameScope der Hauptanwendung zu verschmelzen, wenn sie mit der Hauptobjektstruktur der Anwendung verbunden wird. Nachdem Sie die Bäume verbunden haben, verfügt Ihre App über einen einheitlichen Objektbaum, aber dieser Baum verfügt über separate XAML-Namensräume. Die Divisionen treten an den Verbindungspunkten zwischen Objekten auf, bei denen Sie festlegen, dass eine Eigenschaft der von einem XamlReader.Load-Aufruf zurückgegebene Wert ist.
Die Komplikation bei diskreten und getrennten XAML-NameScopes besteht darin, dass Aufrufe der FindName-Methode sowie direkte verwaltete Objektverweise nicht mehr mit einem einheitlichen XAML-NameScope ausgeführt werden. Stattdessen impliziert das bestimmte Objekt, für das FindName aufgerufen wird, den Bereich, wobei der Bereich der XAML-NameScope ist, in dem sich das aufrufende Objekt befindet. Im Direkten Referenzfall für verwaltete Objekte wird der Bereich von der Klasse impliziert, in der der Code vorhanden ist. In der Regel ist der CodeBehind für die Laufzeitinteraktion einer "Seite" von App-Inhalten in der partiellen Klasse vorhanden, die das Stammelement "page" zurückgibt und daher der XAML-NameScope der XAML-Stammnamescope ist.
Wenn Sie FindName aufrufen, um ein benanntes Objekt im XAML-Stamm-NameScope abzurufen, findet die Methode die Objekte nicht aus einem einzelnen XAML-NameScope, der von XamlReader.Load erstellt wurde. Wenn Sie FindName aus einem Objekt aufrufen, das aus dem getrennten XAML-NameScope abgerufen wurde, findet die Methode keine benannten Objekte im Stamm-XAML-NameScope.
Dieses einzelne XAML-NameScope-Problem wirkt sich nur auf das Suchen von Objekten nach Namen in XAML-NameScopes aus, wenn der FindName-Aufruf verwendet wird.
Um Verweise auf Objekte abzurufen, die in einem anderen XAML-NameScope definiert sind, können Sie verschiedene Techniken verwenden:
- Durchlaufen Sie die gesamte Baumstruktur in einzelnen Schritten mit Parent- und/oder Auflistungseigenschaften, die in der Objektstruktur vorhanden sind (z. B. die von Panel.Children zurückgegebene Auflistung).
- Wenn Sie einen diskreten XAML-NameScope aufrufen und den XAML-Stamm-NameScope wünschen, ist es immer einfach, einen Verweis auf das aktuell angezeigte Hauptfenster abzurufen. Sie können den visuellen Stamm (das STAMM-XAML-Element, auch als Inhaltsquelle bezeichnet) aus dem aktuellen Anwendungsfenster in einer Codezeile mit dem Aufruf
Window.Current.Contentabrufen. Anschließend können Sie zu FrameworkElement umwandeln und FindName aus diesem Kontext aufrufen. - Wenn Sie aus dem XAML-Stamm-NameScope aufrufen und ein Objekt innerhalb eines bestimmten XAML-NameScope verwenden möchten, empfiehlt es sich, im Code vorauszuplanen und einen Verweis auf das Objekt beizubehalten, das von XamlReader.Load zurückgegeben und dann der Hauptobjektstruktur hinzugefügt wurde. Dieses Objekt ist jetzt ein gültiges Objekt zum Aufrufen von FindName innerhalb des diskreten XAML-NameScopes. Sie können dieses Objekt als globale Variable verfügbar halten oder es anderweitig mithilfe von Methodenparametern übergeben.
- Sie können Namen und XAML-Namescope-Überlegungen vollständig vermeiden, indem Sie den visuellen Baum untersuchen. Mit der VisualTreeHelper-API können Sie den visuellen Baum in Bezug auf Elternobjekte und Kindersammlungen, basierend auf Position und Index, durchlaufen.
XAML-NameScopes in Vorlagen
Vorlagen in XAML bieten die Möglichkeit, Inhalte auf einfache Weise wiederzuverwenden und erneut zu verwenden. Vorlagen können jedoch auch Elemente mit Namen enthalten, die auf Vorlagenebene definiert sind. Diese Vorlage kann mehrmals auf einer Seite verwendet werden. Aus diesem Grund definieren Vorlagen ihre eigenen XAML-NameScopes, unabhängig von der Seite, auf die die Formatvorlage oder Vorlage angewendet wird. Betrachten Sie dieses Beispiel:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<Page.Resources>
<ControlTemplate x:Key="MyTemplate">
....
<TextBlock x:Name="MyTextBlock" />
</ControlTemplate>
</Page.Resources>
<StackPanel>
<SomeControl Template="{StaticResource MyTemplate}" />
<SomeControl Template="{StaticResource MyTemplate}" />
</StackPanel>
</Page>
Hier wird dieselbe Vorlage auf zwei verschiedene Steuerelemente angewendet. Wenn Vorlagen keine separaten XAML-Namensbereiche haben, würde der in der Vorlage verwendete Name "MyTextBlock" zu einem Namenskonflikt führen. Jede Instanziierung der Vorlage verfügt über einen eigenen XAML-NameScope. In diesem Beispiel würde der XAML-NameScope der instanziierten Vorlage also genau einen Namen enthalten. Der XAML-Stammnamescope enthält jedoch nicht den Namen aus einer der beiden Vorlagen.
Aufgrund der separaten XAML-Namensbereiche erfordert das Finden benannter Elemente innerhalb einer Vorlage aus dem Bereich der Seite, auf die die Vorlage angewendet wird, eine andere Technik. Anstatt FindName für ein objekt in der Objektstruktur aufzurufen, rufen Sie zuerst das Objekt ab, auf das die Vorlage angewendet wurde, und rufen Dann GetTemplateChild auf. Wenn Sie ein Steuerelementautor sind und eine Konvention generieren, bei der ein bestimmtes benanntes Element in einer angewendeten Vorlage das Ziel für ein Verhalten ist, das vom Steuerelement selbst definiert wird, können Sie die GetTemplateChild-Methode aus dem Implementierungscode des Steuerelements verwenden. Die GetTemplateChild-Methode ist geschützt, sodass nur der Autor des Steuerelements Zugriff darauf hat. Außerdem gibt es Konventionen, die Steuerelementautoren befolgen sollten, um Teile und Vorlagenteile zu benennen und diese als Attributwerte zu melden, die auf die Steuerelementklasse angewendet werden. Diese Technik macht die Namen wichtiger Teile für die Steuerung von Benutzern erkennbar, die möglicherweise eine andere Vorlage anwenden möchten, was die benannten Teile ersetzen muss, um die Steuerungsfunktionalität aufrechtzuerhalten.
Zugehörige Themen
Windows developer