Sdílet prostřednictvím


Erweiterbare Architektur des WPF-Designers

Aktualisiert: November 2007

Der Windows Presentation Foundation (WPF)-Designer für Visual Studio ist eine visuelle Umgebung zum Bearbeiten von zusammengefassten WPF-Steuerelementen, die durch den UserControl-Typ implementiert werden. Der WPF-Designer basiert auf einem Framework mit einer erweiterbaren Architektur zum Erstellen einer eigenen angepassten Entwurfsumgebung.

Durch das Erweitern des WPF-Designer-Objektmodells können die Darstellung zur Entwurfszeit und das Verhalten von WPF-Inhalten in einem bemerkenswerten Maß angepasst werden. Sie können den WPF-Designer beispielsweise auf die folgenden Arten erweitern:

  • Anpassen der Symbole zum Verschieben und Ändern der Größe mit verbesserten Grafiken.

  • Hinzufügen eines Symbols zur Entwurfsoberfläche, das das ausgewählte Steuerelement beim Bewegen des Mauszeigers verzerrt.

  • Ändern der Entwurfszeitdarstellung und des Verhaltens eines Steuerelements über verschiedene Tools hinweg.

Die WPF-Designer-Architektur unterstützt vollständig die beeindruckende Leistungsfähigkeit von WPF. Dadurch wird erstmalig das Erstellen vieler verschiedener visueller Entwurfsumgebungen möglich.

WPF-Designer-Objektmodell

Das WPF-Designer-Objektmodell ist modular aufgebaut. Daher müssen Sie beim Erweitern der Entwurfsoberfläche lediglich die Elemente erweitern, die für die vorgesehenen Features erforderlich sind. Sie müssen nicht viel unterstützenden Code schreiben, um die benutzerdefinierten Entwurfsfeatures zu ermöglichen. 

Das Objektmodell besteht aus fünf Funktionseinheiten, die in der folgenden Tabelle beschrieben werden.

Funktionseinheit

Beschreibung

Bearbeitungsmodell

Programmierschnittstelle für die Objekte im Designer.

Featureanbieter

Wichtigster Erweiterbarkeitspunkt im Designerframework.

Bearbeitungskontext

Zentraler Speicherort für den Zustand eines Designers.

Tools

Tools zum Verarbeiten von Benutzereingaben.

Metadatenspeicher

Speicherort für das Entwurfszeitverhalten eines Steuerelements, um Designerlogik physisch von Laufzeitlogik zu trennen.

Die folgende Abbildung veranschaulicht das WPF-Designer-Objektmodell.

Übergeordnetes Objektmodell

Hinweis:

Der WPF-Designer unterstützt das vollständige Erweiterbarkeitsframework. Von Expression Blend werden nur die Eigenschaften-Editoren, das Laden von Metadaten und die Lizenzierung unterstützt. Von Blend werden keine Menüaktionen und Adorner unterstützt. 

Bearbeitungsmodell

Die Entwurfsumgebung interagiert mit Laufzeitsteuerelementen über eine Programmierschnittstelle, die als Bearbeitungsmodell bezeichnet wird. Das Bearbeitungsmodell besteht aus drei Funktionsuntereinheiten: einem Modell, einem öffentlichen Wrapper zum Abstrahieren des Modells und einer Ansicht, die die Benutzeroberfläche des Modells darstellt.

Die Entwurfsumgebung verwendet den ModelItem-Typ zur Kommunikation mit dem zugrunde liegenden Modell. Alle Änderungen werden an den ModelItem-Wrappern vorgenommen, die sich auf das zugrunde liegende Modell auswirken. Dadurch kann das Modell einfach gehalten werden. Die ModelItem-Wrapper behandeln komplexe Designerfeatures, beispielsweise Transaktionsunterstützung, Verfolgen von Rückgängigfunktionen und Änderungsbenachrichtigungen.

Die ModelService-Klasse stellt den Einstiegspunkt für das Bearbeitungsmodell und globale Ereignisbenachrichtigungen bereit.

Die ViewService-Klasse ordnet den zugrunde liegenden Modellelementen visuelle Darstellungen zu.

Beide Dienste sind erforderlich, damit der Designer funktioniert. Die DesignerView-Klasse, verantwortlich für das Verarbeiten von Benutzereingaben und das Weiterleiten der Eingaben an entsprechende Befehle, benötigt diese beiden Dienste, um die Benutzereingaben wiederum dem Modell korrekt zuzuordnen.

Featureanbieter

Sie erweitern das Entwurfszeitverhalten von Typen, indem Sie die FeatureProvider-Klasse oder die FeatureConnector<FeatureProviderType>-Klasse verwenden. Die FeatureConnector<FeatureProviderType>-Klasse verwaltet eine Liste von FeatureProvider-Objekten.

Die FeatureProvider-Klasse stellt den grundlegendsten Erweiterbarkeitspunkt bereit. Ein Featureanbieter ist ein einfaches Feature oder Add-In, das üblicherweise keine großen Anforderungen an die Entwurfsumgebung stellt und in einem bestimmten Kontext erstellt und zerstört wird. Featureanbieter werden zum Hinzufügen kleiner neuer Benutzeroberflächenelemente zur Entwurfsoberfläche oder zum Anpassen von einfachem Verhalten verwendet. So kann ein Featureanbieter beispielsweise weitere Ziehpunkte oder eine neue Möglichkeit zum Ziehen mit der Maus zur Verfügung stellen.

Leiten Sie von der FeatureConnector<FeatureProviderType>-Klasse ab, um auf die tiefste Ebene der Erweiterbarkeit zuzugreifen. Diese Klasse macht einen Dienstanbieter verfügbar, über den durch abgeleitete Featureconnectorklassen Ereignisse und Anforderungen verarbeitet sowie Dienste veröffentlicht werden können. Beispielsweise können Sie einen Featureconnector implementieren, um eine Auswahloberfläche oder objektspezifische Serialisierung bereitzustellen.

Im Allgemeinen implementieren Sie ein Feature zum Erweitern vorhandener Konzepte. Implementieren Sie einen Featureconnector, um neue Konzepte bereitzustellen. Weitere Informationen finden Sie unter Featureanbieter und Featureverbindungen.

Bearbeitungskontext

Ein wesentlicher Teil der Zustandsinformationen wird in einem ausgeführten Designer akkumuliert. So kann der Designerzustand beispielsweise beinhalten, welche Objekte ausgewählt sind oder welches Verhalten beim Drücken der linken Maustaste ausgelöst wird. Der Zustand des Designers wird an einem zentralen Speicherort gespeichert, damit er bei Bedarf zur Verfügung steht. Die EditingContext-Klasse stellt dieses zentrale Repository für den Designerzustand dar.

Die EditingContext-Klasse trennt den Zustand in zwei Kategorien: Daten und Verhalten. Daten werden in Form einer Tabelle von Kontextelementen und Verhalten in Form einer Tabelle von Diensten gespeichert. Beide Tabellen werden über einen typbasierten Schlüssel indiziert und sind aufzählbar.

Die ContextItem-Klasse enthält einen einzelnen Bestandteil des Designerzustands. Kontextelemente sind unveränderlich, neue Kontextelemente können jedoch vorhandene Kontextelemente ersetzen und so Veränderlichkeit simulieren.

Auf Dienste kann über eine Services-Eigenschaft zugegriffen werden, die eine Instanz von ServiceManager zurückgibt, auf Kontextelemente kann über eine Items-Eigenschaft zugegriffen werden, die eine Instanz von ContextItemManager zurückgibt.

Befehle, Aufgaben und Tools

Die WPF-Designer-Toolarchitektur besteht aus Befehlen, Aufgaben und Tools. 

Ein Befehl ist ein eindeutiger Bezeichner, der ein bestimmtes Verhalten darstellt. Beispielsweise ist "Ausschneiden" ein Befehl, der den aktuellen Text ausschneidet und in die Zwischenablage kopiert. Der Code zum Implementieren des "Ausschneiden"-Befehls variiert von Anwendung zu Anwendung, ja sogar innerhalb einer Anwendung. So besteht beispielsweise das Ausschneiden von Text in einem Word-Dokument aus einer anderen Implementierung als das Ausschneiden von Text im Textsuchfeld desselben Dokuments. Unabhängig von der Implementierung bleibt der Befehl "Ausschneiden" konstant.

Der WPF-Designer erweitert das WPF-Befehlssystem durch Einführung eines Konzepts von Toolbefehlen. Ein Toolbefehl implementiert die ICommand-Schnittstelle und ähnelt der RoutedCommand-Klasse.

Eine Aufgabe verfügt über eine Auflistung von Befehlsbindungen, die Ihnen das Hinzufügen von weitergeleiteten Befehlen ermöglicht. Die DesignerView-Klasse enthält Code, der die gleiche Weiterleitungsstrategie wie Toolbefehle zum Suchen und Ausführen von in Aufgaben definierten weitergeleiteten Befehlen verwendet. Die DesignerView-Klasse ermöglicht Aufgaben, die allgemeine WPF-Befehle unterstützen, z. B. Copy.

Ein Tool ist eine Klasse, die Benutzereingaben verarbeitet. Alle Benutzereingaben erreichen den Designer als ein oder mehrere Eingabeereignisse. Diese Eingabeereignisse werden an das derzeit aktive Tool übergeben, das sie in Eingabebindungen umwandelt. Wenn eine Eingabebindung zurückgegeben wird, wird der Befehl innerhalb der Bindung ausgeführt.

Ein Tool kann den globalen Modus des Designers darstellen. Wenn ein Benutzer beispielsweise Komponenten auf der Entwurfsoberfläche auswählt, ist dieser Auswahlmodus möglich, da das derzeit aktive Tool Eingabebindungen und Befehle zum Behandeln von Auswahlen bereitstellt. Wenn der Benutzer eine neue Instanz eines Steuerelements erstellt, wird ein anderes Tool mit anderen Befehlen aktiviert, die an dieselben Eingabebindungen gebunden werden.

Metadatenspeicher

Im WPF-Designer-Framework werden Metadaten zur Definition des Entwurfszeitverhaltens eines Steuerelements in einer separaten Assembly abgelegt, die als Metadatenspeicher bezeichnet wird. Im .NET Framework 3.5 ist der Metadatenspeicher in codebasierten Attributtabellen mit einer externen XML-Datei mit Verweisen auf Designercode und auf ein Profil implementiert. Verschiedene Tools können verschiedene Metadatenspeicher mit vollkommen unterschiedlichen Designerimplementierungen bereitstellen. Dies entkoppelt das Entwurfszeitverhalten vom Laufzeitverhalten, sodass der Designer unabhängig vom Steuerelement überarbeitet werden kann. Weitere Informationen finden Sie unter Metadatenspeicher.

Designerinstanzerstellung

Die folgenden Schritte veranschaulichen, wie ein Beispieldesignertyp von der WPF-Designer-Umgebung instanziiert werden könnte. Dieses fiktive Beispiel zeigt, wie ein angenommener Designer ein einzelnes Button-Steuerelement auf der Entwurfsoberfläche auswählen könnte.

  1. Der Benutzer ruft eine durch ein Tool definierte Aktion auf und fordert die Erstellung eines benutzerdefinierten Designers an.

  2. Die Entwurfsumgebung listet eine XML-basierte Liste von Feature-zu-Typ-Zuordnungen auf.

  3. Die Entwurfsumgebung fügt diesen Typen benutzerdefinierte Metadaten hinzu, indem sie die TypeDescriptor-Klasse verwendet. Zum Beispiel könnte allen UIElement-Typen, einschließlich davon abgeleiteten Typen, ein GrabHandleProvider zugeordnet werden.

  4. Eine Bearbeitungsfactory erstellt einen Bearbeitungsspeicher, einen Kontext, einen Feature-Manager und füllt den Bearbeitungsspeicher.

  5. Der WPF-Designer listet alle UIElement-Objekte auf, die durch den Bearbeitungsspeicher verfügbar gemacht wurden, und ruft für jedes die InitializeFeatures -Methode auf.

    1. Stellen Sie sich ein Button-Element vor, das in dieser Hierarchie deklariert wurde.

    2. Der FeatureManager sucht nach einem FeatureAttribute für die Schaltfläche. Der FeatureManager findet ein FeatureAttribute vom Typ GrabHandleProvider für die Schaltfläche.

    3. Der FeatureManager setzt die Suche nach dem GrabHandleProvider-Typ fort und findet ein zugeordnetes FeatureConnectorAttribute. Das FeatureConnectorAttribute legt den SelectionConnector fest.

    4. Der FeatureManager ermittelt, dass dieser Host noch nicht vorhanden ist. Der FeatureManager erstellt den SelectionConnector und fügt ihn der Liste aktiver Featurehosts hinzu.

    5. Das SelectionConnector-Objekt beginnt, die Entwurfsoberfläche auf Auswahländerungen zu überwachen. Das SelectionConnector-Objekt ruft außerdem einen Verweis auf die Adornerebene ab.

  6. Der Benutzer ändert die Auswahl und wählt die Schaltfläche aus. Das Entwurfszeittool löst ein Ereignis für die geänderte Auswahl aus.

  7. Der SelectionConnector empfängt diese Benachrichtigung und erstellt alle auswahlbasierten FeatureProvider-Instanzen, die mit dem ausgewählten Objekt verknüpft sind, einschließlich der GrabHandleProvider-Instanz.

  8. Der SelectionConnector fragt eine Liste von Adornern vom GrabHandleProvider ab und fügt sie der Adornerebene hinzu. Ziehpunkte werden um die ausgewählte Schaltfläche herum angezeigt.

WPF-Designerassemblys

Der WPF-Designer besteht aus zahlreichen Assemblys, die zu einer von drei Kategorien gehören: öffentlich, privat oder Visual Studio-spezifisch.

Die öffentlichen Assemblys machen Klassen verfügbar, die Sie zum Hinzufügen von Entwurfszeitlogik zu Steuerelementen verwenden können.

Die privaten und Visual Studio-spezifischen Assemblys definieren den Featuresatz von WPF-Designer und dessen Interaktionen mit Visual Studio. Die folgende Tabelle zeigt, wie WPF-Designer-Features bereitgestellt werden.

Assembly

Öffentliche API

Beschreibung

Microsoft.VisualStudio.Xaml.dll

Nein

Visual Studio SDK-Integrationslogik

Microsoft.Windows.Design.Host.dll

Ja

Öffentliche API zum Hosten von Designer (Visual Studio-spezifisch)

Microsoft.Windows.Design.Developer.dll

Nein

WPF-Designer-Implementierung. Nur die öffentliche API ist eine Attributtabelle.

Microsoft.Windows.Design.Core.dll

Ja

Stellt eine grundlegende Basis für jeden Designer durch einen Dienst, eine Datenschicht und die Bearbeitung von Metadaten bereit. Dies ist die einzige von Expression Blend unterstützte Assembly.

Microsoft.Windows.Design.Extensibility.dll

Ja

Stellt ein Erweiterbarkeitsmodell durch Attribute bereit.

Microsoft.Windows.Design.Interaction.dll

Ja

Stellt Klassen für Benutzereingabe und Anzeige bereit.

Microsoft.Windows.Design.Markup.dll

Ja

Stellt XAML (Extensible Application Markup Language)- und Dokumentmodellmechanismen bereit.

Hinweis:

Assemblys stellen Funktionsgrenzen dar, nicht Namespacegrenzen. Sie werden oft Namespaces antreffen, die mehr als eine Assembly umfassen.

Die Architektur von WPF-Designer und Windows Forms-Designer

Die WPF-Designer-Architektur unterscheidet sich wesentlich von der Architektur von Windows Forms-Designer, die sich durch die IComponent-Schnittstelle und den System.ComponentModel-Namespace auszeichnet. Weitere Informationen finden Sie unter Vergleich der Frameworks des Windows Forms-Designers und des WPF-Designers

Siehe auch

Konzepte

Featureanbieter und Featureverbindungen

Weitere Ressourcen

Entwickeln von Windows Forms-Steuerelementen zur Entwurfszeit

WPF-Designer-Erweiterbarkeit