Gewusst wie: Definieren eines Menübefehls in einem Modellierungsdiagramm
In Visual Studio Ultimate können Sie zusätzliche Menüelemente definieren, die angezeigt werden, wenn der Benutzer mit der rechten Maustaste auf ein UML-Diagramm klickt. Sie können steuern, ob der Menübefehl angezeigt wird und verfügbar ist, wenn der Benutzer mit der rechten Maustaste auf ein Element im Diagramm klickt, und Sie können Code schreiben, der bei Auswahl des Menüelements ausgeführt wird. Sie können diese Erweiterungen in eine Visual Studio Integration Extension (VSIX) verpacken und an andere Visual Studio Ultimate-Benutzer verteilen.
Voraussetzungen
Visual Studio 2010-Visualisierungs- & Modellierungs-SDK. Weitere Informationen finden Sie in der Code Gallery unter Visual Studio-Visualisierungs- und Modellierungs-SDK.
Definieren des Menübefehls
Um für einen UML-Designer einen Menübefehl zu erstellen, müssen Sie eine Klasse erstellen, die das Verhalten des Befehls definiert, und die Klasse in eine Visual Studio-Integrationserweiterung (VSIX) einbetten. Die VSIX fungiert als Container, der den Befehl installieren kann. Es gibt zwei alternative Methoden, einen Menübefehl zu definieren:
Erstellen eines Menübefehls in seiner eigenen VSIX mithilfe einer Projektvorlage. Dies ist die schnellere Methode. Verwenden Sie diese Methode, wenn Sie die Menübefehle nicht mit anderen Erweiterungstypen, z. B. Validierungserweiterungen, benutzerdefinierten Toolboxelementen oder Gestenhandlern, kombinieren möchten.
Erstellen von getrennten Menübefehl- und VSIX-Projekten. Verwenden Sie diese Methode, wenn Sie mehrere Erweiterungstypen in dieselbe VSIX kombinieren möchten. Wenn beispielsweise der Menübefehl erwartet, dass das Modell bestimmte Einschränkungen berücksichtigt, können Sie es in dieselbe VSIX wie eine Validierungsmethode einbetten.
So erstellen Sie einen Menübefehl in einem eigenen VSIX
Klicken Sie im Dialogfeld Neues Projekt unter Modellierungsprojekte auf Befehlserweiterung.
Öffnen Sie die .cs-Datei im neuen Projekt, und ändern Sie die CommandExtension-Klasse, um den Befehl zu implementieren.
Weitere Informationen finden Sie unter Implementieren des Menübefehls.
Sie können diesem Projekt zusätzliche Befehle hinzufügen, indem Sie neue Klassen definieren.
Testen Sie den Menübefehl, indem Sie F5 drücken. Weitere Informationen finden Sie unter Ausführen des Menübefehls.
Installieren Sie den Menübefehl auf einem anderen Computer, indem Sie die vom Projekt erstellte Datei bin\*\*.vsix kopieren. Weitere Informationen finden Sie unter Installieren des Menübefehls.
So erstellen Sie einen separaten Menübefehl in einem Klassenbibliothekprojekt (DLL)
Erstellen Sie in einer neuen Visual Studio-Projektmappe oder in einer vorhandenen Projektmappe ein Klassenbibliotheksprojekt.
Zeigen Sie im Menü Datei auf Neu, und klicken Sie dann auf Projekt.
Klicken Sie unter Installierte Vorlagen auf Visual C# oder auf Visual Basic. Klicken Sie in der mittleren Spalte auf Klassenbibliothek.
Legen Sie Projektmappe fest, um anzugeben, ob eine neue Projektmappe erstellt oder einer bereits geöffneten VSIX-Projektmappe eine Komponente hinzugefügt werden soll.
Legen Sie Name und Speicherort für das Projekt fest, und klicken Sie auf OK.
Fügen Sie dem Projekt die folgenden Verweise hinzu.
Verweis
Optionen
System.ComponentModel.Composition
Definieren von Komponenten per Managed Extensibility Framework (MEF).
Microsoft.VisualStudio.Uml.Interfaces
Lesen und Ändern der Eigenschaften von Modellelementen
Microsoft.VisualStudio.ArchitectureTools.Extensibility
Erstellen von Modellelementen, Ändern von Formen in Diagrammen
Microsoft.VisualStudio.Modeling.Sdk.10.0
Definieren von Modellereignishandlern
Kapseln einer Reihe von Änderungen im Modell. Weitere Informationen finden Sie unter Gewusst wie: Verknüpfen von Modellaktualisierungen mithilfe von Transaktionen.
Microsoft.VisualStudio.Modeling.Sdk.Diagrams.10.0
(nicht immer erforderlich)
Zugreifen auf zusätzliche Diagrammelemente für Gestenhandler
Microsoft.VisualStudio.ArchitectureTools.Extensibility.Layer
Nur für Befehle in Ebenendiagrammen erforderlich. Weitere Informationen finden Sie unter Erstellen von Erweiterungen für Ebenendiagramme.
Definieren Sie Befehle in einem Ebenendiagramm.
Fügen Sie dem Projekt eine Klassendatei hinzu, und legen Sie deren Inhalt auf den folgenden Code fest.
Tipp
Ändern Sie den Namespace, den Klassennamen und den Rückgabewert von Text entsprechend den jeweiligen Anforderungen.
using System.ComponentModel.Composition; using System.Linq; using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Presentation; using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Uml; using Microsoft.VisualStudio.Modeling.ExtensionEnablement; using Microsoft.VisualStudio.Uml.AuxiliaryConstructs; using Microsoft.VisualStudio.Uml.Classes; // ADD other UML namespaces if required namespace UMLmenu1 // CHANGE { // DELETE any of these attributes if the command // should not appear in some types of diagram. [ClassDesignerExtension] [ActivityDesignerExtension] [ComponentDesignerExtension] [SequenceDesignerExtension] [UseCaseDesignerExtension] // [LayerDesignerExtension] // if you have installed Feature Pack 1 // All menu commands must export ICommandExtension: [Export (typeof(ICommandExtension))] // CHANGE class name public class Menu1 : ICommandExtension { [Import] public IDiagramContext DiagramContext { get; set; } public void QueryStatus(IMenuCommand command) { // Set command.Visible or command.Enabled to false // to disable the menu command. command.Visible = command.Enabled = true; } public string Text { get { return "MENU COMMAND LABEL"; } } public void Execute(IMenuCommand command) { // A selection of starting points: IDiagram diagram = this.DiagramContext.CurrentDiagram; foreach (IShape<IElement> shape in diagram.GetSelectedShapes<IElement>()) { IElement element = shape.Element; } IModelStore modelStore = diagram.ModelStore; IModel model = modelStore.Root; foreach (IElement element in modelStore.AllInstances<IClass>()) { } } } }
Weitere Informationen zum Füllen der Methoden finden Sie unter Implementieren des Menübefehls.
Sie müssen den Menübefehl einem VSIX-Projekt hinzufügen, das als Container für die Installation des Befehls fungiert. Gegebenenfalls können Sie in dasselbe VSIX auch weitere Komponenten einschließen.
So fügen Sie einem VSIX-Projekt einen separaten Menübefehl hinzu
Diese Prozedur ist nicht erforderlich, wenn Sie den Menübefehl mit seiner eigenen VSIX erstellt haben.
Erstellen Sie ein VSIX-Projekt, sofern die Projektmappe noch kein VSIX-Projekt enthält.
Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf die Projektmappe, zeigen Sie auf Hinzufügen, und klicken Sie anschließend auf Neues Projekt.
Erweitern Sie unter Installierte Vorlagen den Knoten Visual C# oder Visual Basic, und klicken Sie anschließend auf Erweiterungen. Klicken Sie in der mittleren Spalte auf VSIX Project.
Legen Sie das VSIX-Projekt als Startprojekt der Projektmappe fest.
Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das VSIX-Projekt, und klicken Sie anschließend auf Als Startprojekt festlegen.
Fügen Sie in source.extension.vsixmanifest unter Inhalt das Klassenbibliotheksprojekt als MEF-Komponente hinzu.
Öffnen Sie source.extension.vsixmanifest.
Klicken Sie auf Inhalt hinzufügen.
Wählen Sie für Inhaltstyp auswählen die Option MEF-Komponente aus.
Klicken Sie in Quelle auswählen auf Projekt, und wählen Sie den Namen des Klassenbibliotheksprojekts aus.
Klicken Sie auf Editionen auswählen, und wählen Sie die Visual Studio-Editionen aus, unter denen die Erweiterung ausgeführt werden soll.
Legen Sie den Namen und die Beschreibungsfelder des VSIX fest. Speichern Sie die Datei.
Implementieren des Menübefehls
Durch die Menübefehlsklasse werden die erforderlichen Methoden für ICommandExtension implementiert.
string Text { get; } |
Geben Sie die Bezeichnung des Menüelements zurück. |
void QueryStatus(IMenuCommand command); |
Wird aufgerufen, wenn der Benutzer im Diagramm mit der rechten Maustaste klickt. Diese Methode sollte das Modell nicht ändern. Verwenden Sie DiagramContext.CurrentDiagram.SelectedShapes, um festzulegen, ob der Befehl angezeigt werden soll und aktiviert sein soll. Legen Sie Folgendes fest:
|
void Execute (IMenuCommand command); |
Wird aufgerufen, wenn Benutzer auf das Menüelement klicken, während es sichtbar und aktiviert ist.
|
Zugriff auf das Modell im Code
Schließen Sie die folgende Deklaration in die Menübefehlsklasse ein:
[Import] public IDiagramContext DiagramContext { get; set; }
...
Die IDiagramContext-Deklaration ermöglicht es Ihnen, in den Methoden Code zu schreiben, der auf das Diagramm, die aktuelle Auswahl und das Modell zugreift:
IDiagram diagram = this.DiagramContext.CurrentDiagram;
foreach (IShape<IElement> shape in diagram.GetSelectedShapes<IElement>())
{ IElement element = shape.Element; ... }
IModelStore modelStore = diagram.ModelStore;
IModel model = modelStore.Root;
foreach (IElement element in modelStore.AllInstances<IUseCase>()) {...}
Navigieren im Modell und Aktualisieren des Modells
Alle Elemente des UML-Modells sind über die API verfügbar. In der aktuellen Auswahl oder im Stamm des Modells können Sie auf alle anderen Elemente zugreifen. Weitere Informationen finden Sie unter Gewusst wie: Navigieren im UML-Modell und Programmieren mit der UML-API.
Wenn Sie mit einem Sequenzdiagramm arbeiten, finden Sie unter Gewusst wie: Bearbeiten von Sequenzdiagrammen mit der UML-API weitere Informationen.
Die API ermöglicht Ihnen auch das Ändern von Elementeigenschaften, Löschen von Elementen und Beziehungen und Erstellen neuer Elemente und Beziehungen.
Standardmäßig wird jede Änderung, die Sie in der Execute-Methode vornehmen, in einer separaten Transaktion ausgeführt. Der Benutzer kann jede Änderung einzeln rückgängig machen. Wenn Sie die Änderungen in einer Transaktion gruppieren möchten, verwenden Sie eine ILinkedUndoTransaction. Informationen dazu finden Sie unter Gewusst wie: Verknüpfen von Modellaktualisierungen mithilfe von Transaktionen.
Verwenden des UI-Threads für Updates
In einigen Fällen kann es nützlich sein, Updates am Modell mit einem Hintergrundthread auszuführen. Wenn der Befehl z. B. Daten aus einer langsamen Ressource lädt, können Sie den Ladevorgang in einem Hintergrundthread ausführen, damit der Benutzer die Änderungen in Echtzeit verfolgen und ggf. abbrechen kann.
Dabei ist jedoch zu beachten, dass der Modellspeicher nicht threadsicher ist. Sie sollten Updates immer mit dem UI-Thread (Benutzeroberflächenthread) ausführen und nach Möglichkeit verhindern, dass der Benutzer während der Ausführung des Hintergrundprozesses Änderungen vornimmt. Ein Beispiel finden Sie unter Gewusst wie: Aktualisieren eines UML-Modells aus einem Hintergrundthread.
Ausführen des Menübefehls
Führen Sie den Befehl zu Testzwecken im Debugmodus aus.
So testen Sie den Menübefehl
Drücken Sie F5, oder klicken Sie im Menü Debuggen auf Debuggen starten.
Eine experimentelle Instanz von Visual Studio wird gestartet.
Problembehandlung: Wenn ein neuer Visual Studio nicht startet:
Wenn Sie mehr als ein Projekt haben, stellen Sie sicher, dass das VSIX-Projekt als Startprojekt der Projektmappe festgelegt wird.
Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Startprojekt oder das einzige Projekt, und klicken Sie dann auf Eigenschaften. Klicken Sie im Projekteigenschaften-Editor auf die Registerkarte Debuggen. Stellen Sie sicher, dass die Zeichenfolge im Feld Externes Programm starten der vollständige Pfadname von Visual Studio ist. Dieser lautet in der Regel:
C:\Programme\Microsoft Visual Studio 10.0\Common7\IDE\devenv.exe
Öffnen oder erstellen Sie in der experimentellen Instanz von Visual Studio ein Modellierungsprojekt, und öffnen oder erstellen Sie ein Modellierungsdiagramm. Verwenden Sie ein Diagramm, das zu einem der Typen gehört, die in den Attributen der Menübefehlsklasse aufgeführt sind.
Klicken Sie mit der rechten Maustaste auf eine beliebige Stelle im Diagramm. Der Befehl muss im Menü angezeigt werden.
Problembehandlung: Wenn der Befehl nicht im Menü angezeigt wird, stellen Sie Folgendes sicher:
Das Menübefehlsprojekt ist im VSIX-Projekt als MEF-Komponente in source.extensions.manifest in der Liste Inhalt aufgeführt.
Die Parameter des Import-Attributs und des Export-Attributs sind gültig.
Die QueryStatus-Methode legt das command.Enabled-Feld bzw. das Visible-Feld nicht auf false fest.
Der verwendete Modelldiagrammtyp (UML-Klasse, Sequenz usw.) ist als eines der Menübefehlsklassen-Attribute [ClassDesignerExtension], [SequenceDesignerExtension] usw. aufgeführt.
Installieren und Deinstallieren einer Erweiterung
Sie können eine Visual Studio-Erweiterung sowohl auf Ihrem eigenen Computer als auch auf anderen Computern installieren.
So installieren Sie eine Erweiterung
Suchen Sie auf dem Computer nach der .vsix-Datei, die vom VSIX-Projekt erstellt wurde.
Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das VSIX-Projekt, und klicken Sie dann auf Ordner in Windows Explorer öffnen.
Suchen Sie nach der Datei bin\*\IhrProjekt.vsix.
Kopieren Sie die .vsix-Datei auf den Zielcomputer, auf dem Sie die Erweiterung installieren möchten. Dies kann Ihr eigener Computer oder ein anderer Computer sein.
Der Zielcomputer muss über eine der Editionen von Visual Studio verfügen, die Sie in source.extension.vsixmanifest angegeben haben.
Doppelklicken Sie auf dem Zielcomputer auf die .vsix-Datei.
Installer für Visual Studio-Erweiterungen wird geöffnet, und die Erweiterung wird installiert.
Starten Sie Visual Studio, bzw. starten Sie die Anwendung neu.
So deinstallieren Sie eine Erweiterung
Klicken Sie im Menü Extras auf Erweiterungs-Manager.
Erweitern Sie Installierte Erweiterungen.
Wählen Sie die Erweiterung aus, und klicken Sie dann auf Deinstallieren.
In seltenen Fällen kann es vorkommen, dass eine fehlerhafte Erweiterung nicht geladen und ein Bericht im Fehlerfenster erstellt wird, aber im Erweiterungs-Manager keine Informationen angezeigt werden. Sie haben die Möglichkeit, die Erweiterung zu entfernen, indem Sie die Datei aus dem folgenden Ordner löschen:
%LocalAppData%\Local\Microsoft\VisualStudio\10.0\Extensions
Beispiel
Das folgende Beispiel zeigt den Code für einen Menübefehl, der die Namen von zwei Elementen eines Klassendiagramms austauscht. Dieser Code muss in einem Visual Studio-Erweiterungsprojekt erstellt und wie in den vorherigen Abschnitten beschrieben installiert werden.
using System.Collections.Generic; // for IEnumerable
using System.ComponentModel.Composition;
// for [Import], [Export]
using System.Linq; // for IEnumerable extensions
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Presentation;
// for IDiagramContext
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Uml;
// for designer extension attributes
using Microsoft.VisualStudio.Modeling.Diagrams;
// for ShapeElement
using Microsoft.VisualStudio.Modeling.ExtensionEnablement;
// for IGestureExtension, ICommandExtension, ILinkedUndoContext
using Microsoft.VisualStudio.Uml.Classes;
// for class diagrams, packages
/// <summary>
/// Extension to swap names of classes in a class diagram.
/// </summary>
namespace SwapClassNames
{
// Declare the class as an MEF component:
[Export(typeof(ICommandExtension))]
[ClassDesignerExtension]
// Add more ExportMetadata attributes to make
// the command appear on diagrams of other types.
public class NameSwapper : ICommandExtension
{
// MEF required interfaces:
[Import]
public IDiagramContext Context { get; set; }
[Import]
public ILinkedUndoContext LinkedUndoContext { get; set; }
/// <summary>
/// Swap the names of the currently selected elements.
/// </summary>
/// <param name="command"></param>
public void Execute(IMenuCommand command)
{
// Get selected shapes that are IClassifiers -
// IClasses, IInterfaces, IEnumerators.
var selectedShapes = Context.CurrentDiagram
.GetSelectedShapes<IClassifier>();
if (selectedShapes.Count() < 2) return;
// Get model elements displayed by shapes.
IClassifier firstElement = selectedShapes.First().Element;
IClassifier lastElement = selectedShapes.Last().Element;
// Do the swap in a transaction so that user
// cannot undo one change without the other.
using (ILinkedUndoTransaction transaction =
LinkedUndoContext.BeginTransaction("Swap names"))
{
string firstName = firstElement.Name;
firstElement.Name = lastElement.Name;
lastElement.Name = firstName;
transaction.Commit();
}
}
/// <summary>
/// Called by Visual Studio to determine whether
/// menu item should be visible and enabled.
/// </summary>
public void QueryStatus(IMenuCommand command)
{
int selectedClassifiers = Context.CurrentDiagram
.GetSelectedShapes<IClassifier>().Count();
command.Visible = selectedClassifiers > 0;
command.Enabled = selectedClassifiers == 2;
}
/// <summary>
/// Name of the menu command.
/// </summary>
public string Text
{
get { return "Swap Names"; }
}
}
}
Siehe auch
Weitere Ressourcen
Gewusst wie: Definieren und Installieren einer Modellierungserweiterung
Erweitern von UML-Modellen und Diagrammen
Gewusst wie: Definieren eines benutzerdefinierten Elements für die Modellerstellungstoolbox
Gewusst wie: Definieren von Validierungseinschränkungen für UML-Modelle
Gewusst wie: Bearbeiten von Sequenzdiagrammen mit der UML-API
Beispiel: Befehl zum Ausrichten von Formen in einem UML-Diagramm