XAML-NamescopesXAML namescopes

Ein XAML-NameScope speichert Beziehungen zwischen den definierten XAML-Namen von Objekten und ihren entsprechenden Instanzen.A XAML namescope stores relationships between the XAML-defined names of objects and their instance equivalents. Dieses Konzept ähnelt der umfassenderen Bedeutung des Begriffs " Namescope " in anderen Programmiersprachen und-Technologien.This concept is similar to the wider meaning of the term namescope in other programming languages and technologies.

Definieren von XAML-NameScopesHow XAML namescopes are defined

Die Namen in XAML-NameScopes aktivieren Benutzercode, der auf die Objekte verweist, die ursprünglich in XAML definiert wurden.Names in XAML namescopes enable user code to reference the objects that were initially declared in XAML. Das interne Ergebnis der XAML-Analyse ist das Erstellen eines Satzes von Objekten, in dem einige oder alle Beziehungen dieser Objekte in den XAML-Deklarationen beibehalten werden.The internal result of parsing XAML is that the runtime creates a set of objects that retain some or all of the relationships these objects had in the XAML declarations. Diese Beziehungen werden als spezifische Objekteigenschaften der erstellten Objekte beibehalten oder für Hilfsmethoden in den Programmiermodell-APIs verfügbar gemacht.These relationships are maintained as specific object properties of the created objects, or are exposed to utility methods in the programming model APIs.

Die typischste Verwendung eines Namens in einem XAML-NameScope ist der direkte Verweis auf eine Objektinstanz, die vom Markupkompilierungsschritt aktiviert wird, in Kombination mit einer generierten InitializeComponent-Methode in den partiellen Klassenvorlagen.The most typical use of a name in a XAML namescope is as a direct reference to an object instance, which is enabled by the markup compile pass as a project build action, combined with a generated InitializeComponent method in the partial class templates.

Sie können auch die FindName-Hilfsmethode zur Laufzeit verwenden, um einen Verweis auf Objekte zurückzugeben, die mit einem Namen im XAML-Markup definiert wurden.You can also use the utility method FindName yourself at run time to return a reference to objects that were defined with a name in the XAML markup.

Mehr zu Buildaktionen und XAMLMore about build actions and XAML

Technisch gesehen wird für das XAML selbst ein Markupcompilerdurchlauf durchgeführt, während gleichzeitig das XAML und die darin für CodeBehind definierte partielle Klasse gemeinsam kompiliert werden.What happens technically is that the XAML itself undergoes a markup compiler pass at the same time that the XAML and the partial class it defines for code-behind are compiled together. Jedes Objektelement, für das im Markup ein Name- oder x:Name-Attribut definiert wurde, generiert ein internes Feld mit einem Namen, der mit dem XAML-Namen übereinstimmt.Each object element with a Name or x:Name attribute defined in the markup generates an internal field with a name that matches the XAML name. Dieses Feld ist anfänglich leer.This field is initially empty. Die Klasse generiert dann eine InitializeComponent-Methode, die erst aufgerufen wird, wenn das gesamte XAML geladen wurde.Then the class generates an InitializeComponent method that is called only after all the XAML is loaded. Anschließend werden durch die InitializeComponent-Logik alle internen Felder mit dem FindName-Rückgabewert für die entsprechende Namenszeichenfolge aufgefüllt.Within the InitializeComponent logic, each internal field is then populated with the FindName return value for the equivalent name string. Sie können diese Infrastruktur selbst erkennen, indem Sie sich die Dateien mit der Erweiterung ".g" (generiert) ansehen, die für die einzelnen XAML-Seiten nach der Kompilierung im /obj-Unterordner eines Projekts für eine Windows-Runtime-App erstellt werden.You can observe this infrastructure for yourself by looking at the ".g" (generated) files that are created for each XAML page in the /obj subfolder of a Windows Runtime app project after compilation. Sie können die Felder und die InitializeComponent-Methode auch als Member der erstellten Assemblys anzeigen, wenn Sie eine Reflexion über diese ausführen oder in anderer Weise ihre MSIL-Inhalte untersuchen.You can also see the fields and InitializeComponent method as members of your resulting assemblies if you reflect over them or otherwise examine their interface language contents.

Hinweis    Speziell für Visual C++ Komponenten Erweiterungen (C++/CX)-apps wird ein dahinter liegendes Feld für einen x:Namensverweis nicht für das Stamm Element einer XAML-Datei erstellt.Note  Specifically for Visual C++ component extensions (C++/CX) apps, a backing field for an x:Name reference is not created for the root element of a XAML file. Wenn Sie aus CodeBehind für C++/CX auf das Stammobjekt verweisen müssen, verwenden Sie andere APIs oder eine Strukturausnahme.If you need to reference the root object from C++/CX code-behind, use other APIs or tree traversal. Sie können beispielsweise erst FindName für ein bekanntes benanntes Unterelement und anschließend Parent aufrufen.For example you can call FindName for a known named child element and then call Parent.

Erstellen von Objekten zur Laufzeit mit XamlReader.LoadCreating objects at run time with XamlReader.Load

XAML kann auch als Zeichenfolgeneingabe für die XamlReader.Load-Methode verwendet werden, die analog zum ursprünglichen XAML-Quellanalysevorgang funktioniert.XAML can be also be used as the string input for the XamlReader.Load method, which acts analogously to the initial XAML source parse operation. XamlReader.Load erstellt zur Laufzeit eine neue getrennte Struktur von Objekten.XamlReader.Load creates a new disconnected tree of objects at run time. Die getrennte Struktur kann dann an die Hauptobjektstruktur angefügt werden.The disconnected tree can then be attached to some point on the main object tree. Sie müssen die erstellte Objektstruktur explizit verbinden, entweder durch Hinzufügen zu einer Inhaltseigenschaftenauflistung wie Children oder durch Festlegen einer anderen Eigenschaft, die einen Objektwert akzeptiert (z. B. Laden eines neuen ImageBrush für einen Fill-Eigenschaftswert).You must explicitly connect your created object tree, either by adding it to a content property collection such as Children, or by setting some other property that takes an object value (for example, loading a new ImageBrush for a Fill property value).

XAML-NameScope-Auswirkungen von XamlReader.LoadXAML namescope implications of XamlReader.Load

Der vorläufige XAML-NameScope, der durch die neue mit XamlReader.Load erstellte Objektstruktur definiert wird, wertet alle definierten Namen im bereitgestellten XAML auf Eindeutigkeit hin aus.The preliminary XAML namescope defined by the new object tree created by XamlReader.Load evaluates any defined names in the provided XAML for uniqueness. Wenn das bereitgestellte XAML zu diesem Zeitpunkt intern nicht eindeutige Namen enthält, wird durch XamlReader.Load eine Ausnahme ausgelöst.If names in the provided XAML are not internally unique at this point, XamlReader.Load throws an exception. Beim Verbinden der getrennten Objektstruktur mit der Hauptobjektstruktur der Anwendung wird nicht versucht, den zugehörigen XAML-NameScope mit dem XAML-Haupt-NameScope der Anwendung zusammenzuführen.The disconnected object tree does not attempt to merge its XAML namescope with the main application XAML namescope, if or when it is connected to the main application object tree. Nach dem Verbinden der Strukturen weist die App eine einheitliche Objektstruktur auf, die jedoch einzelne XAML-NameScopes enthält.After you connect the trees, your app has a unified object tree, but that tree has discrete XAML namescopes within it. Die Trennungen treten an den Verbindungspunkten zwischen Objekten auf, an denen Sie Eigenschaften auf den Wert festlegen, der von einem XamlReader.Load-Aufruf zurückgegeben wird.The divisions occur at the connection points between objects, where you set some property to be the value returned from a XamlReader.Load call.

Das Problem mit einzelnen und getrennten XAML-NameScopes besteht darin, dass Aufrufe der FindName-Methode sowie direkte verwaltete Objektverweise nicht mehr für einen einheitlichen XAML-NameScope durchgeführt werden können.The complication of having discrete and disconnected XAML namescopes is that calls to the FindName method as well as direct managed object references no longer operate against a unified XAML namescope. Stattdessen impliziert das bestimmte Objekt, für das FindName aufgerufen wird, den Bereich. Dabei ist der Bereich der XAML-NameScope, in dem sich das aufrufende Objekt befindet.Instead, the particular object that FindName is called on implies the scope, with the scope being the XAML namescope that the calling object is within. Bei direkten verwalteten Objektverweisen wird der Bereich durch die Klasse impliziert, die den Code enthält.In the direct managed object reference case, the scope is implied by the class where the code exists. In der Regel ist der CodeBehind für Laufzeitinteraktionen einer "Seite" mit App-Inhalt in der partiellen Klasse vorhanden, auf der die "Seite" für den Stamm basiert. Aus diesem Grund fungiert der XAML-NameScope XAML-Stamm-NameScope.Typically, the code-behind for run-time interaction of a "page" of app content exists in the partial class that backs the root "page", and therefore the XAML namescope is the root XAML namescope.

Wenn Sie FindName aufrufen, um ein benanntes Objekt aus dem XAML-Stamm-NameScope abzurufen, findet die Methode keine Objekte aus einem mit XamlReader.Load erstellten einzelnen XAML-NameScope.If you call FindName to get a named object in the root XAML namescope, the method will not find the objects from a discrete XAML namescope created by XamlReader.Load. Umgekehrt findet die Methode keine benannten Objekte im XAML-Stamm-NameScope, wenn Sie FindName von einem Objekt aus aufrufen, das sich in einem einzelnen XAML-NameScope befindet.Conversely, if you call FindName from an object obtained from out of the discrete XAML namescope, the method will not find named objects in the root XAML namescope.

Dieses Problem mit einzelnen XAML-NameScopes wirkt sich nur auf Objektsuchen nach Namen in XAML-NameScopes aus, die mithilfe des FindName-Aufrufs durchgeführt werden.This discrete XAML namescope issue only affects finding objects by name in XAML namescopes when using the FindName call.

Um Verweise auf Objekte abzurufen, die in einem anderen XAML-NameScope definiert werden, stehen mehrere Vorgehensweisen zur Verfügung:To get references to objects that are defined in a different XAML namescope, you can use several techniques:

  • Durchlaufen Sie die gesamte Struktur in separaten Schritten mit über geordneten und/oder Auflistungs Eigenschaften, die bekanntermaßen in der Objektstruktur vorhanden sind (z. b. die Auflistung, die von Panel. Childrenzurückgegeben wurde).Walk the entire tree in discrete steps with Parent and/or collection properties that are known to exist in your object tree structure (such as the collection returned by Panel.Children).
  • Wenn Sie den Aufruf von einem einzelnen XAML-NameScope aus durchführen und auf den XAML-Stamm-NameScope abzielen, bietet es sich an, einen Verweis auf das gegenwärtig angezeigte Hauptfenster abzurufen.If you are calling from a discrete XAML namescope and want the root XAML namescope, it is always easy to get a reference to the main window currently displayed. Sie können den visuellen Stamm (das XAML-Stammelement, das auch als Inhaltsquelle bezeichnet wird) aus der aktuellen Anwendung in einer Codezeile mit dem Window.Current.Content-Aufruf abrufen.You can get the visual root (the root XAML element, also known as the content source) from the current application window in one line of code with the call Window.Current.Content. Sie können dann eine Umwandlung in FrameworkElement durchführen und von diesem Bereich aus FindName aufrufen.You can then cast to FrameworkElement and call FindName from this scope.
  • Wenn Sie den Aufruf vom XAML-Stamm-NameScope aus ausführen und auf ein Objekt in einem einzelnen XAML-NameScope abzielen, bietet es sich an, in Ihrem Code vorauszuplanen und einen Verweis auf das Objekt beizubehalten, das von XamlReader.Load und anschließend der Hauptobjektstruktur hinzugefügt wurde.If you are calling from the root XAML namescope and want an object within a discrete XAML namescope, the best thing to do is to plan ahead in your code and retain a reference to the object that was returned by XamlReader.Load and then added to the main object tree. Dieses Objekt ist jetzt ein gültiges Objekt zum Aufrufen von FindName innerhalb des einzelnen XAML-NameScopes.This object is now a valid object for calling FindName within the discrete XAML namescope. Speichern Sie dieses Objekt als globale Variable, oder übergeben Sie es mit Methodenparametern.You could keep this object available as a global variable or otherwise pass it by using method parameters.
  • Sie können Probleme hinsichtlich Namen und XAML-NameScope vermeiden, indem Sie die visuelle Struktur untersuchen.You can avoid names and XAML namescope considerations entirely by examining the visual tree. Die VisualTreeHelper-API ermöglicht es Ihnen, die visuelle Struktur im Hinblick auf übergeordnete Objekte und untergeordnete Auflistungen auf Grundlage von Position und Index zu durchlaufen.The VisualTreeHelper API enables you to traverse the visual tree in terms of parent objects and child collections, based purely on position and index.

XAML-NameScopes in VorlagenXAML namescopes in templates

Mithilfe von Vorlagen in XAML können Sie Inhalt auf einfache Weise wiederverwenden und erneut anwenden. Vorlagen können jedoch auch Elemente mit Namen enthalten, die auf Vorlagenebene definiert wurden.Templates in XAML provide the ability to reuse and reapply content in a straightforward way, but templates might also include elements with names defined at the template level. Dieselbe Vorlage wird möglicherweise mehrmals auf einer Seite verwendet.That same template might be used multiple times in a page. Deshalb definieren Vorlagen ihre eigenen XAML-NameScopes, und zwar unabhängig von der Seite, auf die der Stil oder die Vorlage angewendet wird.For this reason, templates define their own XAML namescopes, independent of the containing page where the style or template is applied. Sehen Sie sich dieses Beispiel an:Consider this example:

<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.Here, the same template is applied to two different controls. Wenn die Vorlagen keine getrennten XAML-NameScopes enthalten würden, würde der in der Vorlage verwendete MyTextBlock-Name einen Namenskonflikt auslösen.If templates did not have discrete XAML namescopes, the "MyTextBlock" name used in the template would cause a name collision. Jede Vorlageninstanz hat ihren eigenen XAML-Namescope, weshalb in diesem Beispiel der Namescope jeder Instanz der Vorlage genau einen Namen enthält.Each instantiation of the template has its own XAML namescope, so in this example each instantiated template's XAML namescope would contain exactly one name. Der XAML-Stamm-NameScope enthält jedoch keinen der Vorlagennamen.However, the root XAML namescope does not contain the name from either template.

Wegen der separaten XAML-NameScopes erfordert die Suche nach benannten Elementen innerhalb einer Vorlage vom Bereich der Seite, auf die die Vorlage angewendet wird, ein anderes Verfahren.Because of the separate XAML namescopes, finding named elements within a template from the scope of the page where the template is applied requires a different technique. Statt FindName für ein Objekt in der Objektstruktur aufzurufen, rufen Sie zunächst das Objekt ab, auf das die Vorlage angewendet wurde. Rufen Sie dann GetTemplateChild auf.Rather than calling FindName on some object in the object tree, you first obtain the object that has the template applied, and then call GetTemplateChild. Wenn Sie Autor eines Steuerelements sind und eine Konvention erstellen, in der ein bestimmtes benanntes Element in einer angewendeten Vorlage das Ziel für ein Verhalten darstellt, das vom Steuerelement selbst definiert wird, können Sie die GetTemplateChild-Methode aus dem Code zur Implementierung des Steuerelements verwenden.If you are a control author and you are generating a convention where a particular named element in an applied template is the target for a behavior that is defined by the control itself, you can use the GetTemplateChild method from your control implementation code. Die GetTemplateChild-Methode ist geschützt, sodass nur der Steuerelementautor Zugriff darauf hat.The GetTemplateChild method is protected, so only the control author has access to it. Außerdem gibt es Konventionen, die Steuerelementautoren befolgen sollten, um Teile und Vorlagenteile zu benennen und diese als auf die Steuerelementklasse angewendete Attributwerte zu melden.Also, there are conventions that control authors should follow in order to name parts and template parts and report these as attribute values applied to the control class. Diese Vorgehensweise macht die Namen wichtiger Teile für die Benutzer von Steuerelementen erkennbar, die möglicherweise eine andere Vorlage anwenden möchten, die die benannten Teile ersetzen müsste, um die Funktionalität der Steuerelemente aufrechtzuerhalten.This technique makes the names of important parts discoverable to control users who might wish to apply a different template, which would need to replace the named parts in order to maintain control functionality.