Gewusst wie: Hinzufügen eines Befehls zum Kontextmenü
Menübefehle können Sie den domänenspezifischen Sprache (DSL) hinzufügen, damit die Benutzer Aufgaben ausführen können, die dem DSL spezifisch sind.Die Befehle werden im Menü des Kontexts (Kurzform), wenn Benutzer im Diagramm mit der rechten Maustaste auf.Sie können einen Befehl definieren, sodass sie nur unter bestimmten Umständen im Menü wird angezeigt.Sie können z. B. den Befehl nur, wenn der Benutzer auf bestimmte Typen des Elements klickt, oder die Elemente in bestimmten Zuständen sichtbar zu machen.
Zusammenfassend sind die Schritte im DslPackage-Projekt ausgeführt wie folgt:
Deklarieren Sie den Befehl in Commands.vsct
Aktualisieren Sie die Versionsnummer des Pakets in Package.tt.Dies ist erforderlich, wenn Sie Commands.vsct ändern
Schreiben von Methoden in der CommandSet-Klasse , um den Befehl sichtbar zu machen und zu definieren, was Sie den Befehl erneut ausführen möchten.
Beispiele finden Sie unter. Visualization and Modeling SDK website
![]() |
---|
Sie können das Verhalten etwas vorhandener Befehle wie Ausschneiden auch ändern, und alle Methoden in überschreibenden Drucken über CommandSet.cs einfügen auswählen.Weitere Informationen finden Sie unter Gewusst wie: Ändern eines Standardmenübefehls in einer domänenspezifischen Sprache. |
Definieren eines Befehls mit MEF
Verwaltetes Erweiterungs-Framework (MEF) stellt eine alternative Methode zum Definieren von Menübefehlen im Menü im Diagramm bereit.Sein Hauptobjekt ist ein von Ihnen oder anderen Seiten zu erweiternde DSL zu aktivieren.Benutzer können auswählen, dass nur das DSL zu installieren und DSL können das oder die Erweiterungen installieren.MEF verringert jedoch auch die Arbeit des Kontextmenüs Definieren von Befehlen, nachdem die ursprüngliche Arbeit mit MEF auf dem DSL zu aktivieren.
Verwenden Sie die Methode in diesem Thema:
Sie möchten in Menüs Menübefehle Gegensatz zum Kontextmenü definieren.
Sie möchten bestimmte Gruppierungen der Befehle im Menü definieren.
Sie sollten keine anderen aktivieren, um das DSL mit ihren eigenen Befehle zu erweitern.
Sie möchten nur einen Befehl definieren.
Andernfalls sollten Sie die MEF-Methode anwenden, um Befehle zu definieren.Weitere Informationen finden Sie unter Erweitern von DSL mittels MEF.
Deklarieren Sie den Befehl in Commands.Vsct
Menübefehle werden in DslPackage \ Commands.vsct deklariert.Diese Definitionen geben die Bezeichnungen an der Menüelemente und wo sie in den Menüs angezeigt werden.
Die Datei, die Sie bearbeiten, Commands.vsct, Definitionen von einigen .h-Dateien importieren, die im Verzeichnis \ Visual Studio-SDK installieren PfadVisualStudioIntegration \ Common \ Inc. sind.Es enthält außerdem GeneratedVsct.vsct ein, das aus der DSL-Definition generiert wird.
Weitere Informationen zu .vsct-Dateien finden Sie unter (Visual Studio-Befehls-Tabelle. Dateien Vsct).
Um den Befehl hinzu
In Projektmappen-Explorerunter dem DslPackage Projekt, öffnen Sie Commands.vsct.
Im Commands-Element definieren Sie eine oder mehrere Schaltflächen und eine Gruppe.Eine Schaltfläche ist ein Element im Menü.Eine Gruppe ist ein Abschnitt im Menü.Um diese Elemente zu definieren, fügen Sie die folgenden Elemente hinzu:
<!-- Define a group - a section in the menu --> <Groups> <Group guid="guidCustomMenuCmdSet" id="grpidMyMenuGroup" priority="0x0100"> <!-- These symbols are defined in GeneratedVSCT.vsct --> <Parent guid="guidCmdSet" id="menuidContext" /> </Group> </Groups> <!-- Define a button - a menu item - inside the Group --> <Buttons> <Button guid="guidCustomMenuCmdSet" id="cmdidMyContextMenuCommand" priority="0x0100" type="Button"> <Parent guid="guidCustomMenuCmdSet" id="grpidMyMenuGroup"/> <!-- If you do not want to place the command in your own Group, use Parent guid="guidCmdSet" id="grpidContextMain". These symbols are defined in GeneratedVSCT.vsct --> <CommandFlag>DynamicVisibility</CommandFlag> <Strings> <ButtonText>My Context Menu Command</ButtonText> </Strings> </Button> </Buttons>
Hinweis
Jede Schaltfläche oder Gruppe wird durch eine GUID und eine ganze Zahl identifiziert.Sie können einige Schaltflächen und Gruppen mit dem gleichen GUID erstellen.Allerdings müssen sie unterschiedliche IDs haben.Die GUID-Namen Namen und IDs werden in tatsächlichem GUID und der numerischen ID im <Symbols> Knoten übersetzt.
Fügen Sie eine Sichtbarkeits KEY-Einschränkung für den Befehl hinzu, sodass sie nur im Kontext von domänenspezifischen Sprache geladen wird.Weitere Informationen finden Sie unter VisibilityConstraints-Element.
Hierzu fügen Sie die folgenden Elemente im CommandTable-Element nach dem Commands-Element hinzu.
<VisibilityConstraints> <!-- Ensures the command is only loaded for this DSL --> <VisibilityItem guid="guidCustomMenuCmdSet" id="cmdidMyContextMenuCommand" context="guidEditor"/> </VisibilityConstraints>
Definieren Sie die Namen, die Sie für die guids und die ID frei.Hierzu fügen Sie ein Symbols-Element im CommandTable-Element nach dem Commands-Element hinzu.
<Symbols> <!-- Substitute a unique GUID for the placeholder: --> <GuidSymbol name="guidCustomMenuCmdSet" value="{00000000-0000-0000-0000-000000000000}" > <IDSymbol name="grpidMyMenuGroup" value="0x01001"/> <IDSymbol name="cmdidMyContextMenuCommand" value="0x00001"/> </GuidSymbol> </Symbols>
Ersetzen Sie {000...000} durch eine GUID, die die Gruppen und die Menüelemente identifiziert.Zum Abrufen eines neuen GUID, verwenden Sie das Tool GUID erstellen im Menü Extras .
Hinweis
Wenn Sie mehrere Gruppen oder Menüelemente hinzufügen, können Sie das gleiche GUID verwenden.Sie müssen jedoch neue Werte für IDSymbolsverwenden.
In Code, den Sie in dieser Prozedur kopiert haben, ersetzen Sie alle Vorkommen der folgenden Zeichenfolgen als Zeichenfolgen, besitzen:
grpidMyMenuGroup
cmdidMyContextMenuCommand
guidCustomMenuCmdSet
Das Kontextmenü-Befehl
Aktualisieren Sie die Paket-Version in Package.tt
Jedes Mal, wenn Sie einen Befehl hinzufügen oder ändern, aktualisieren Sie den version-Parameter ProvideMenuResourceAttribute Paket auf die Klasse angewendet wird, bevor Sie die neue Version einer domänenspezifischen Sprache freigeben.
Da die Paket Klasse in einer generierten Datei definiert ist, aktualisieren Sie das Attribut in der Textvorlagendatei, die die Package.cs-Datei generiert.
So aktualisieren Package.tt-Datei
In Projektmappen-Explorerim DslPackage Projekt im Ordner GeneratedCode , öffnen Sie die Package.tt-Datei.
Suchen Sie das ProvideMenuResource-Attribut.
Erhöhen Sie den version-Parameter des Attributs, das der zweite Parameter ist.Wenn Sie möchten, können Sie den Parameternamen explizit schreiben, um Sie an ihren Zweck zu beachten.Beispiele:
[VSShell::ProvideMenuResource("1000.ctmenu", version: 2 )]
Definieren Sie das Verhalten des Befehls
Das DSL hat bereits einige Befehle, die in einer partiellen Klasse implementiert werden, die in DslPackage GeneratedCode " \ \ CommandSet.cs deklariert ist.Um neue Befehle hinzuzufügen, müssen Sie diese Klasse erweitern, indem Sie eine neue Datei erstellen, die eine partielle Deklaration derselben Klasse enthält.Der Name der Klasse ist normalerweise <YourDslName> CommandSet.So beginnen Sie mit empfiehlt sich, den Namen der Klasse überprüft und dessen Inhalt überprüft.
Die festgelegte Klasse des Befehls wird von CommandSetabgeleitet.
So erweitern CommandSet-Klasse
Öffnen Sie im Projektmappen-Explorer im DslPackage-Projekt, den GeneratedCode-Ordner, und klicken Sie dann unter Suchen und öffnen CommandSet.tt die generierte Datei CommandSet.cs.Beachten Sie den Namespace und den Namen der ersten Klasse, die es definiert ist.Beispielsweise wird:
namespace Company.Language1
{ ... internal partial class Language1CommandSet : ...
In DslPackageerstellen Sie einen Ordner mit dem Namen benutzerdefinierten Code.Erstellen Sie in diesem Ordner eine neue Klassendatei mit dem Namen CommandSet.cs.
In der neuen Datei schreiben Sie eine partielle Deklaration, die denselben Namespace und Namen wie die generierte partielle Klasse hat.Beispiele:
namespace Company.Language1 /* Make sure this is correct */
{ internal partial class Language1CommandSet { ...
Hinweis, wenn Sie die Klassenvorlage verwenden, um die neue Datei zu erstellen, müssen Sie den Namespace und den Klassennamen beheben.
Erweitern Sie die Klasse des Befehls
Der festgelegte Code des Befehls muss in der Regel die folgenden Namespaces importieren:
using System;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.Linq;
using Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling.Diagrams;
using Microsoft.VisualStudio.Modeling.Shell;
Passen Sie den Namespace und den Klassennamen, um die im generierten CommandSet.cs entspricht:
namespace Company.Language1 /* Make sure this is correct */
{
// Same class as the generated class.
internal partial class Language1CommandSet
{
Sie müssen zwei Möglichkeiten, eine, um zu bestimmen, wann sich der Befehl im Kontextmenü angezeigt wird und die andere zum Definieren des auszuführenden Befehls.Diese Methoden sind keine Überschreibungen. stattdessen registrieren Sie sie in einer Liste von Befehlen.
Definieren Sie, ob der Befehl angezeigt wird
Für jeden Befehl definieren Sie eine OnStatus...-Methode, die bestimmt, ob der Befehl für das Menü angezeigt wird und ob er aktiviert und abgeblendet dargestellt wird.Legen Sie die Visible und Enabled-Eigenschaften MenuCommand, wie im folgenden Beispiel gezeigt.Diese Methode wird aufgerufen, um das Kontextmenü jedes Mal neu zu erstellen, dass der Benutzer auf das Diagramm mit der rechten Maustaste klickt. Daher muss er schneller arbeiten.
In diesem Beispiel ist der Befehl nur sichtbar, wenn der Benutzer einen bestimmten Typ Form ausgewählt hat, und ist nur aktiviert, wenn mindestens eines der ausgewählten Elemente in einem bestimmten Zustand befindet.Das Beispiel basiert auf der Vorlage des Klassendiagramms DSL, und ClassShape und ModelClass sind Typen, die im DSL definiert sind:
private void OnStatusMyContextMenuCommand(object sender, EventArgs e)
{
MenuCommand command = sender as MenuCommand;
command.Visible = command.Enabled = false;
foreach (object selectedObject in this.CurrentSelection)
{
ClassShape shape = selectedObject as ClassShape;
if (shape != null)
{
// Visibility depends on what is selected.
command.Visible = true;
ModelClass element = shape.ModelElement as ModelClass;
// Enabled depends on state of selection.
if (element != null && element.Comments.Count == 0)
{
command.Enabled = true;
return; // seen enough
} } } }
Die folgenden Fragmente sind in OnStatus-Methoden häufig nützlich:
this.CurrentSelection.Klicken Sie auf die Form, die der Benutzer mit der rechten Maustaste geklickt hat, wird immer in dieser Liste enthalten.Wenn der Benutzer auf einen leeren Bereich des Diagramms klickt, wird das Diagramm einziger Member der Liste.
this.IsDiagramSelected() - true , wenn der Benutzer auf einen leeren Bereich des Diagramms geklickt hat.
this.IsCurrentDiagramEmpty()
this.IsSingleSelection() - der Benutzer die nicht mehrere Objekte aus
this.SingleSelection - auf die Form oder das Diagramm, die der Benutzer mit der rechten Maustaste geklickt hat
shape.ModelElement as MyLanguageElement - Das Modellelement, dargestellt durch eine Form.
Im Allgemeinen lassen Sie die Visible-Eigenschaft abhängen, was auf aktiviert ist, und die Eigenschaft Enabled vom Zustand der ausgewählten Elemente abhängig sind.
Eine OnStatus-Methode sollte den Zustand des Speichers nicht ändern.
Definieren Sie, wie der Befehl ausführt
Für jeden Befehl definieren Sie eine OnMenu...-Methode, die die erforderliche Aktion ausführt, wenn der Benutzer auf den Menübefehl klickt.
Wenn Sie Änderungen vornehmen, müssen Sie Modellelemente innerhalb einer Transaktion.Weitere Informationen finden Sie unter Gewusst wie: Ändern eines Standardmenübefehls in einer domänenspezifischen Sprache.
In diesem Beispiel werden ClassShape, ModelClassund Comment-Typen, die im DSL definiert werden, das von der Vorlage des Klassendiagramms DSL abgeleitet ist.
private void OnMenuMyContextMenuCommand(object sender, EventArgs e)
{
MenuCommand command = sender as MenuCommand;
Store store = this.CurrentDocData.Store;
// Changes to elements and shapes must be performed in a Transaction.
using (Transaction transaction =
store.TransactionManager.BeginTransaction("My command"))
{
foreach (object selectedObject in this.CurrentSelection)
{
// ClassShape is defined in my DSL.
ClassShape shape = selectedObject as ClassShape;
if (shape != null)
{
// ModelClass is defined in my DSL.
ModelClass element = shape.ModelElement as ModelClass;
if (element != null)
{
// Do required action here - for example:
// Create a new element. Comment is defined in my DSL.
Comment newComment = new Comment(element.Partition);
// Every element must be the target of an embedding link.
element.ModelRoot.Comments.Add(newComment);
// Set properties of new element.
newComment.Text = "This is a comment";
// Create a reference link to existing object.
element.Comments.Add(newComment);
}
}
}
transaction.Commit(); // Don't forget this!
}
}
Weitere Informationen zum Erstellen von Objekt zu Objekt im Modell und navigiert zur Verwendung von Objekten und Verbindungen finden Sie unter Gewusst wie: Ändern eines Standardmenübefehls in einer domänenspezifischen Spracheerstellt wird.
Registrieren Sie den Befehl
Überprüfen Sie in C# die Deklarationen der GUID-Wert und ID-Werte, die Sie im Abschnitt mit CommandSet.vsct Symbol An:
private Guid guidCustomMenuCmdSet =
new Guid("00000000-0000-0000-0000-000000000000");
private const int grpidMyMenuGroup = 0x01001;
private const int cmdidMyContextMenuCommand = 1;
Verwenden Sie denselben GUID-Wert, wie Sie in Commands.vscteingefügt haben.
![]() |
---|
Wenn Sie den Abschnitt der VSCT-Datei Symbol ändern, müssen Sie diese Deklarationen auch ändern.Sie sollten die Versionsnummer erhöhen auch in Package.tt |
Registrieren Sie die Menübefehle als Teil dieses Befehls festgelegten.GetMenuCommands() wird einmal aufgerufen, wenn das Diagramm erneut initialisiert wird:
protected override IList<MenuCommand> GetMenuCommands()
{
// Get the list of generated commands.
IList<MenuCommand> commands = base.GetMenuCommands();
// Add a custom command:
DynamicStatusMenuCommand myContextMenuCommand =
new DynamicStatusMenuCommand(
new EventHandler(OnStatusMyContextMenuCommand),
new EventHandler(OnMenuMyContextMenuCommand),
new CommandID(guidCustomMenuCmdSet, cmdidMyContextMenuCommand));
commands.Add(myContextMenuCommand);
// Add more commands here.
return commands;
}
Testen Sie den Befehl
Erstellen und Ausführen der DSL in einer experimentellen Instanz von Visual Studio aus.Der Befehl sollte im Kontextmenü in Situationen angezeigt werden, die Sie angegeben haben.
So testen Sie den Befehl
Projektmappen-Explorer Klicken Sie auf der Symbolleiste auf Alle Vorlagen transformieren.
Drücken Sie F5 , um die Projektmappe zu erstellen, und starten Sie das Debuggen einer domänenspezifischen Sprache in der experimentellen Build.
Öffnen Sie in der experimentellen Build B. ein Diagramm.
Verschiedene Elemente klicken Sie mit der rechten Maustaste im Diagramm zu überprüfen, dass der Befehl aktiviert oder deaktiviert ist und ordnungsgemäß dargestellt wurde oder sich in Abhängigkeit vom ausgewählten Element ausgeblendet.
Problembehandlung
Der Befehl wird nicht im Menü angezeigt:
Der Befehl wird nur in Debuginstanzen von Visual Studio, bis Sie das DSL-Paket installieren.Weitere Informationen finden Sie unter Bereitstellen von domänenspezifischen Sprachlösungen.
Stellen Sie sicher, dass die experimentelle Beispiel die richtige Dateinamenerweiterung für diesen DSL verfügt.Um die Dateinamenerweiterung zu untersuchen, öffnen Sie DslDefinition.dsl in der primären Instanz von Visual Studio.Dann in DSL-Explorer Editor mit der rechten Maustaste auf den Knoten, und klicken Sie dann auf Eigenschaften.Stellen Sie im Eigenschaftenfenster sicher die FileExtensions-Eigenschaft.
Taten Sie Erhöhen Sie die Versionsnummer des Pakets?
Legen Sie einen Haltepunkt am Anfang der OnStatus-Methode fest.Es sollte unterbrechen wenn Sie mit der rechten Maustaste über einem Teil des Diagramms.
OnStatus-Methode wird nicht aufgerufen:
Stellen Sie sicher, dass die GUID und ID im Abschnitt CommandSet-Code die im Symbol aus Commands.vsct übereinstimmt.
In Commands.vsct stellen Sie sicher, dass die GUID und ID in jedem übergeordneten Knoten die richtige übergeordnete Gruppe angibt.
Klicken Sie in einer Visual Studio-Eingabeaufforderung geben Sie devenv Ausdruck /rootsuffix " /setup " ein.Starten Sie dann die Debuginstanz von Visual Studio.
Wenden Sie die OnStatus-Methode, um diesen Befehl zu überprüfen. Sichtbar und Command. Enabled auf True festgelegt werden.
Fehlerhafter Befehl angezeigt oder Menütext an der falschen Stelle angezeigt:
Überprüfen Sie, ob die Kombination der GUID und ID für diesen Befehl eindeutig ist.
Stellen Sie sicher, dass Sie frühere Versionen des Pakets deinstalliert haben.
Siehe auch
Konzepte
Gewusst wie: Ändern eines Standardmenübefehls in einer domänenspezifischen Sprache
Weitere Ressourcen
Schreiben von Code zum Anpassen einer domänenspezifischen Sprache