Strukturen in WPF

In vielen Technologien sind Elemente und Komponenten in einer Baumstruktur angeordnet, in der Entwickler Objektknoten direkt bearbeiten können, um das Rendering und das Verhalten einer Anwendung zu beeinflussen. Windows Presentation Foundation (WPF) verwendet ebenfalls verschiedene Strukturmodelle, um Beziehungen zwischen Programmelementen zu definieren. Größtenteils können WPF-Entwickler eine Anwendung in Code erstellen oder Teile der Anwendung in XAML definieren, während sie sich als Konzept die Objektstrukturmetapher vorstellen. Sie rufen hierfür jedoch eine bestimmte API auf oder verwenden bestimmtes Markup und verwenden keine allgemeine API für die Objektstrukturmanipulation, so wie dies in XML-DOM der Fall wäre. WPF macht zwei Hilfsklassen verfügbar, die eine Strukturmetaphernansicht bereitstellen: LogicalTreeHelper und VisualTreeHelper. Die Begriffe visuelle Struktur und logische Struktur werden auch in der WPF-Dokumentation verwendet, da diese Strukturen nützlich sind, um das Verhalten bestimmter WPF-Schlüsselfunktionen nachzuvollziehen. In diesem Thema wird definiert, was die visuelle Struktur und die logische Struktur darstellen, es wird der Bezug dieser Strukturen zu einem allgemeinen Objektstrukturkonzept erläutert, und es werden LogicalTreeHelper und VisualTreeHelpers eingeführt.

Dieses Thema enthält folgende Abschnitte.

  • Strukturen in WPF
  • Die logische Struktur
  • Die visuelle Struktur
  • Strukturen, Inhaltselemente und Inhaltshosts
  • Strukturdurchlauf
  • Routen für Routingereignisse in Form einer "Struktur"
  • Ressourcenwörterbücher und Strukturen
  • Verwandte Abschnitte

Strukturen in WPF

Die umfassendste Struktur in WPF ist die Objektstruktur. Wenn Sie eine Anwendungsseite in XAML definieren und dann XAML laden, wird die Struktur basierend auf den Schachtelungsbeziehungen der Elemente im Markup erstellt. Wenn Sie eine Anwendung oder einen Teil der Anwendung im Code definieren, wird die Struktur basierend darauf erstellt, wie Sie Eigenschaftswerte für Eigenschaften zuweisen, die das Inhaltsmodell für ein bestimmtes Objekt implementieren. In Windows Presentation Foundation (WPF) gibt es zwei Verfahren, mit denen die vollständige Objektstruktur konzeptualisiert und an die öffentliche API gemeldet wird: als logische Struktur und visuelle Struktur. Die Unterschiede zwischen logischer Struktur und visueller Struktur sind nicht immer von großer Wichtigkeit, aber es können gelegentlich Probleme mit bestimmten WPF-Subsystemen oder bei bestimmten Auswahlen in Markup oder Code auftreten.

Obwohl Sie die logische oder die visuelle Struktur nicht immer direkt bearbeiten, hilft Ihnen die Kenntnis der Interaktion von Strukturen dabei, WPF als Technologie zu verstehen. Die Vorstellung von WPF als Strukturmetapher ist außerdem wichtig, um die Funktion der Eigenschaftenvererbung und des Ereignisroutings in WPF zu verstehen.

HinweisHinweis

Da die Objektstruktur eher ein Konzept als eine tatsächliche API ist, kann das Konzept auch als Objektdiagramm betrachtet werden.In der Praxis bestehen zur Laufzeit Beziehungen zwischen Objekten, die mit der Strukturmetapher nicht mehr abgebildet werden können.Trotzdem ist die Strukturmetapher insbesondere bei XAML-definierter Benutzeroberfläche ausreichend relevant, sodass in der WPF-Dokumentation meistens der Begriff Objektstruktur verwendet wird, wenn auf dieses allgemeine Konzept verwiesen wird.

Die logische Struktur

In WPF fügen Sie Benutzeroberflächenelementen Inhalt hinzu, indem Sie Eigenschaften der Objekte festlegen, die diese Elemente unterstützen. Zum Beispiel fügen Sie Elemente einem ListBox-Steuerelement hinzu, indem Sie seine Items-Eigenschaft ändern. Dabei fügen Sie Elemente in die ItemCollection ein, bei der es sich um den Items-Eigenschaftswert handelt. Entsprechend bearbeiten Sie zum Hinzufügen von Objekten zu einem DockPanel seinen Children-Eigenschaftswert. Hier fügen Sie Objekte der UIElementCollection hinzu. Ein Codebeispiel finden Sie unter Gewusst wie: Dynamisches Hinzufügen eines Elements.

Wenn Sie in Extensible Application Markup Language (XAML) Listenelemente in ein ListBox-Element oder Steuerelemente oder andere Benutzeroberflächenelemente in ein DockPanel-Element einfügen, verwenden Sie die Eigenschaften Items und Children wie im folgenden Beispiel (entweder explizit oder implizit).

<DockPanel
  Name="ParentElement"
  xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
  >
  <!--implicit: <DockPanel.Children>-->
  <ListBox DockPanel.Dock="Top">
    <!--implicit: <ListBox.Items>-->
    <ListBoxItem>
      <TextBlock>Dog</TextBlock>
    </ListBoxItem>
    <ListBoxItem>
      <TextBlock>Cat</TextBlock>
    </ListBoxItem>
    <ListBoxItem>
      <TextBlock>Fish</TextBlock>
    </ListBoxItem>
  <!--implicit: </ListBox.Items>-->
  </ListBox>
  <Button Height="20" Width="100" DockPanel.Dock="Top">Buy a Pet</Button>
  <!--implicit: </DockPanel.Children>-->
</DockPanel>

Wenn Sie diesen XAML-Code als XML unter einem Dokumentobjektmodell verarbeiten würden und die Tags auskommentiert als implizit eingeschlossen hätten (dies wäre gültig), hätte die resultierende XML-DOM-Struktur Elemente für <ListBox.Items> und die anderen impliziten Elemente eingeschlossen. Die XAML-Verarbeitung erfolgt jedoch beim Lesen des Markups und Schreiben in Objekte jedoch anders, und das resultierende Objektdiagramm schließt ListBox.Items nicht tatsächlich ein. Es verfügt jedoch über die ListBox-Eigenschaft Items, die eine ItemCollection enthält, und diese ItemCollection wird initialisiert, ist jedoch leer, wenn der ListBox-XAML-Code verarbeitet wird. Dann wird jedes untergeordnete Objektelement, das als Inhalt für die ListBox vorhanden ist, der ItemCollection durch Parseraufrufe von ItemCollection.Add hinzugefügt. Dieses Beispiel für die Verarbeitung von XAML in eine Objektstruktur ist bisher offenbar ein Beispiel dafür, dass die erstellte Objektstruktur im Grunde die logische Struktur ist.

Die logische Struktur entspricht jedoch nicht dem ganzen Objektdiagramm, das zur Laufzeit für die Anwendungsbenutzeroberfläche vorhanden ist, auch wenn die impliziten XAML-Syntaxelemente nicht berücksichtigt werden. Der Hauptgrund hierfür sind grafische Elemente und Vorlagen. Betrachten Sie z. B. den Button. Die logische Struktur meldet das Button-Objekt sowie seine Zeichenfolge Content. Zu dieser Schaltfläche gehört jedoch mehr als die Laufzeitobjektstruktur. Genauer wird die Schaltfläche nur deshalb auf eine bestimmte Weise auf dem Bildschirm angezeigt, weil eine bestimmte Button-Steuerelementvorlage angewendet wurde. Die grafischen Elemente, die aus einer angewendeten Vorlage stammen (z. B. der in der Vorlage definierte dunkelgraue Border um die visuelle Schaltfläche), werden nicht in der logischen Struktur gemeldet, auch wenn Sie die logische Struktur während der Laufzeit betrachten (z. B. das Behandeln eines Eingabeereignisses aus der sichtbaren Benutzeroberfläche und das anschließende Lesen der logischen Struktur). Wenn Sie die grafischen Elemente der Vorlage suchen, müssen Sie stattdessen die visuelle Struktur untersuchen.

Weitere Informationen zur Zuordnung der XAML-Syntax zum erstellten Objektdiagramm sowie zur impliziten Syntax in XAML finden Sie unter Ausführliche Erläuterung der XAML-Syntax oder Übersicht über XAML (WPF)

Der Zweck der logischen Struktur

Die logische Struktur wird verwendet, damit Inhaltsmodelle ihre potenziellen untergeordneten Objekte auf einfache Weise durchlaufen können und damit Inhaltsmodelle erweiterbar sind. Außerdem stellt die logische Struktur ein Framework für bestimmte Benachrichtigungen bereit, z. B. wenn alle Objekte in der logischen Struktur geladen sind. Im Grunde ist die logische Struktur eine Approximation eines Laufzeitobjektdiagramms auf Frameworkebene, die grafische Elemente ausschließt, die jedoch für viele Abfragevorgänge bei der Zusammensetzung der eigenen Laufzeitanwendung adäquat ist.

Außerdem werden sowohl statische als auch dynamische Ressourcenverweise aufgelöst, indem aufwärts durch die logische Struktur nach Resources-Auflistungen für das anfängliche anfordernde Objekt gesucht wird. Danach wird aufwärts in der logischen Struktur fortgefahren und jedes FrameworkElement (oder FrameworkContentElement) auf einen anderen Resources-Wert durchsucht, der ein ResourceDictionary enthält und möglicherweise diesen Schlüssel enthält. Die logische Struktur wird für die Ressourcensuche verwendet, wenn sowohl die logische Struktur als auch die visuelle Struktur vorhanden ist. Weitere Informationen zu Ressourcenwörterbüchern und der Suche finden Sie unter Übersicht über Ressourcen.

Zusammensetzung der logischen Struktur

Die logische Struktur wird auf WPF-Frameworkebene definiert. Dies bedeutet, dass das WPF-Basiselement, das für logische Strukturoperationen am meisten relevant ist, FrameworkElement oder FrameworkContentElement lautet. Wenn Sie die LogicalTreeHelper-API tatsächlich verwenden, können Sie jedoch sehen, dass die logische Struktur in einigen Fällen Knoten enthält, die weder FrameworkElement noch FrameworkContentElement sind. Die logische Struktur meldet z. B. den Text-Wert eines TextBlock, der eine Zeichenfolge ist.

Überschreiben der logischen Struktur

Entwickler von erweiterten Steuerelementen können die logische Struktur überschreiben, indem sie mehrere APIs überschreiben, die definieren, wie ein allgemeines Objekt- oder Inhaltsmodell Objekte in der logischen Struktur hinzufügt oder entfernt. Ein Beispiel für die Überschreibung der logischen Struktur finden Sie unter Gewusst wie: Überschreiben der logischen Struktur.

Vererbung von Eigenschaftswerten

Die Vererbung von Eigenschaftswerten wird mithilfe einer Hybridstruktur durchgeführt. Die eigentlichen Metadaten, in denen die Inherits-Eigenschaft enthalten ist, die die Vererbung von Eigenschaften ermöglicht, ist die FrameworkPropertyMetadata-Klasse der WPF-Frameworkebene. Aus diesem Grund muss sowohl das übergeordnete Element, das den Ursprungswert enthält, als auch das untergeordnete Objekt, das diesen Wert erbt, den Typ FrameworkElement oder FrameworkContentElement aufweisen. Außerdem müssen beide Elemente Teil einer logischen Struktur sein. Bei vorhandenen WPF-Eigenschaften, die Eigenschaftenvererbung unterstützen, kann die Eigenschaftswertvererbung jedoch über ein dazwischenliegendes Objekt hinweg beibehalten werden, das sich nicht in der logischen Struktur befindet. Dies ist in erster Linie relevant, wenn Vorlagenelemente geerbte Eigenschaftswerte verwenden sollen, die entweder für die auf Vorlagen basierte Instanz festgelegt wurden oder auf noch höheren Ebenen der Zusammensetzung auf Seitenebene und daher höher in der logischen Struktur. Damit die Vererbung von Eigenschaftswerten über eine solche Grenze hinweg einheitlich funktionieren kann, muss die erbende Eigenschaft als angefügte Eigenschaft registriert werden, und Sie sollten dieses Muster beibehalten, wenn Sie eine benutzerdefinierte Abhängigkeitseigenschaft mit Eigenschaftenvererbungsverhalten definieren möchten. Die genaue Struktur, die für die Vererbung von Eigenschaften verwendet wird, kann von einer Hilfsklassen-Dienstmethode nicht vorausgesehen werden, auch nicht zur Laufzeit. Weitere Informationen finden Sie unter Vererbung von Eigenschaftswerten.

Die visuelle Struktur

Zusätzlich zum Begriff der logischen Struktur gibt es in WPF auch den Begriff der visuellen Struktur. Die visuelle Struktur beschreibt die Struktur von visuellen Objekten, die von der Visual-Basisklasse dargestellt werden. Wenn Sie für ein Steuerelement eine Vorlage schreiben, definieren Sie die visuelle Struktur (bzw. definieren diese neu), die für das Steuerelement gilt. Die visuelle Struktur ist auch für Entwickler interessant, die aus Leistungs- und Optimierungsgründen eine weniger umfangreiche Zeichnungssteuerung bevorzugen. Eine Art der Offenlegung der visuellen Struktur als Teil der herkömmlichen WPF-Anwendungsprogrammierung besteht darin, dass die Ereignisrouten für ein Routingereignis meist entlang der visuellen Struktur verlaufen, nicht entlang der logischen Struktur. Dieses Detail des Verhaltens von Routingereignissen ist nicht offensichtlich, besonders wenn Sie kein Entwickler von Steuerelementen sind. Das Routing von Ereignissen über die visuelle Struktur ermöglicht es Steuerelementen, die die Komposition auf der visuellen Ebene implementieren, Ereignisse zu behandeln oder Ereignissetter zu erstellen.

Strukturen, Inhaltselemente und Inhaltshosts

Inhaltselemente (Klassen, die von ContentElement abgeleitet sind) sind nicht Teil der visuellen Struktur. Sie erben nicht von Visual und weisen keine visuelle Darstellung auf. Um auf einer Benutzeroberfläche überhaupt angezeigt zu werden, muss ContentElement von einem Inhaltshost gehostet werden, bei dem es sich sowohl um ein Visual-Element und ein Element einer logischen Struktur handelt. In der Regel ist ein solches Objekt ein FrameworkElement. Sie können es sich so vorstellen, dass der Inhaltshost für den Inhalt eine Art "Browser" darstellt und wählt, wie der Inhalt innerhalb des Bildschirmbereichs angezeigt wird, den der Host steuert. Wenn der Inhalt gehostet wird, kann der Inhalt zu einem Teilnehmer von bestimmten Strukturabläufen gemacht werden, die normalerweise der visuellen Struktur zugeordnet sind. Im Allgemeinen enthält die FrameworkElement-Hostklasse Implementierungscode, der ein gehostetes ContentElement der Ereignisroute jeweils über Unterknoten der logischen Inhaltsstruktur hinzufügt. Dabei macht es nichts, dass der gehostete Inhalt nicht Teil der wahren visuellen Struktur ist. Dies ist erforderlich, damit ein ContentElement ein Routingereignis finden kann, dessen Weiterleitung an alle Elemente außer sich selbst erfolgt.

Strukturdurchlauf

Die LogicalTreeHelper-Klasse stellt für das Durchlaufen der logischen Struktur die Methoden GetChildren, GetParent und FindLogicalNode bereit. In den meisten Fällen sollte es nicht erforderlich sein, dass Sie die logische Struktur von vorhandenen Steuerelementen durchlaufen, da diese Steuerelemente ihre logischen untergeordneten Elemente fast ausschließlich als dedizierte Auflistungseigenschaft offenlegen, die Auflistungszugriff wie Add, einen Indexer usw. unterstützt. Der Strukturdurchlauf wird vor allem von Steuerelemententwicklern verwendet, die nicht von den geplanten Steuerelementmustern abweichen möchten, z. B. ItemsControl oder Panel, für die Auflistungseigenschaften bereits definiert sind, und die ihre eigene Unterstützung für Auflistungseigenschaften bereitstellen möchten.

Die visuelle Struktur unterstützt ebenfalls eine Hilfsklasse für das Durchlaufen der visuellen Struktur, und zwar VisualTreeHelper. Die visuelle Struktur wird über steuerelementspezifische Eigenschaften nicht auf sehr benutzerfreundliche Weise offengelegt. Aus diesem Grund ist die VisualTreeHelper-Klasse zu empfehlen, um die visuelle Struktur zu durchlaufen, falls dies in Ihrem Programmierszenario erforderlich ist. Weitere Informationen finden Sie unter Übersicht über das WPF-Grafikrendering.

HinweisHinweis

In einigen Fällen ist es notwendig, die visuelle Struktur einer angewendeten Vorlage zu untersuchen.Beim Verwenden dieser Technik sollten Sie vorsichtig vorgehen.Auch wenn Sie eine visuelle Struktur für ein Steuerelement durchlaufen, wobei Sie die Vorlage definieren, können Consumer des Steuerelements immer die Vorlage ändern, indem sie die Template-Eigenschaft für Instanzen festlegen. Sogar der Endbenutzer kann die angewendete Vorlage beeinflussen, indem er das Systemdesign ändert.

Routen für Routingereignisse in Form einer "Struktur"

Wie bereits erwähnt, folgt die Route eines gegebenen Routingereignisses einem einzelnen und vorherbestimmten Pfad in einer Struktur, die ein Hybrid aus der visuellen und der logischen Strukturdarstellung ist. Die Ereignisroute kann in der Struktur nach oben oder unten verlaufen, abhängig davon, ob es sich um ein Tunneling- oder Bubblingroutingereignis handelt. Das Ereignisroutenverfahren verfügt nicht über eine direkt unterstützende Hilfsklasse, die verwendet werden könnte, um die Ereignisroute unabhängig vom Auslösen eines entsprechenden Ereignisses zu durchlaufen. Es gibt eine Klasse, die die Route darstellt (EventRoute), aber die Methoden dieser Klasse sind normalerweise nur für die interne Verwendung gedacht.

Ressourcenwörterbücher und Strukturen

Die Ressourcenwörterbuchsuche für alle in einer Seite definierten Resources durchläuft im Grunde die logische Struktur. Objekte, die sich nicht in der logischen Struktur befinden, können auf Ressourcen mit Schlüssel verweisen, aber die Ressourcensuchsequenz beginnt an dem Punkt, an dem das Objekt mit der logischen Struktur verbunden ist. In WPF können nur die Knoten einer logischen Struktur über eine Resources-Eigenschaft verfügen, die ein ResourceDictionary enthält. Aus diesem Grund ergibt es keinen Sinn, die visuelle Struktur auf der Suche nach Ressourcen mit Schlüssel aus einem ResourceDictionary zu durchlaufen.

Die Ressourcensuche kann jedoch auch über die unmittelbare logische Struktur hinaus durchgeführt werden. Bei Anwendungsmarkup kann die Ressourcensuche dann mit Ressourcenwörterbüchern auf Anwendungsebene und anschließend mit Designunterstützungs- und Systemwerten fortgesetzt werden, auf die als statische Eigenschaften oder Schlüssel verwiesen wird. Designs können auch selbst auf Systemwerte außerhalb der logischen Designstruktur verweisen, wenn die Ressourcenverweise dynamischer Natur sind. Weitere Informationen zu Ressourcenwörterbüchern und der Suchlogik finden Sie unter Übersicht über Ressourcen.

Siehe auch

Konzepte

Übersicht über die Eingabe

Übersicht über das WPF-Grafikrendering

Übersicht über Routingereignisse

Initialisierung für Objektelemente außerhalb einer Objektstruktur

WPF-Architektur