Sdílet prostřednictvím


Přidání příkazu do místní nabídky

Příkazy nabídky můžete přidat do jazyka DSL (Domain-Specific Language), aby uživatelé mohli provádět úlohy specifické pro vaši DSL. Příkazy se zobrazí v místní (místní) nabídce, když uživatelé kliknou pravým tlačítkem myši na diagram. Příkaz můžete definovat tak, aby se v nabídce zobrazil pouze za určitých okolností. Příkaz můžete například zobrazit pouze v případě, že uživatel klikne na konkrétní typy elementů nebo prvků v určitých stavech.

V souhrnu jsou kroky provedeny v projektu DslPackage následujícím způsobem:

  1. Deklarace příkazu v commands.vsct

  2. Aktualizujte číslo verze balíčku v Package.tt. Musíte to udělat pokaždé, když změníte příkazy.vsct.

  3. Do třídy CommandSet napište metody, které příkaz zviditelní a definují, co má příkaz udělat.

Poznámka:

Chování některých existujících příkazů, jako jsou Vyjmout, Vložit, Vybrat vše a Tisk, můžete také upravit přepsáním metod v CommandSet.cs. Další informace naleznete v tématu Postupy: Úprava standardního příkazu nabídky.

Definování příkazu pomocí MEF

Rozhraní MEF (Managed Extension Framework) poskytuje alternativní metodu definování příkazů nabídky v nabídce diagramu. Jejím primárním účelem je umožnit, aby vás nebo jiné strany prodloužili DSL. Uživatelé se mohou rozhodnout nainstalovat pouze DSL, nebo mohou nainstalovat DSL i rozšíření. MeF ale také snižuje práci definování příkazů místní nabídky po počáteční práci, která povolí MEF v DSL.

Použijte metodu v tomto tématu, pokud:

  1. Chcete definovat příkazy nabídky v jiných nabídkách než místní nabídka po kliknutí pravým tlačítkem myši.

  2. V nabídce chcete definovat konkrétní seskupení příkazů.

  3. Nechcete ostatním povolit rozšíření DSL vlastními příkazy.

  4. Chcete definovat pouze jeden příkaz.

    V opačném případě zvažte použití metody MEF k definování příkazů. Další informace naleznete v tématu Rozšíření DSL pomocí MEF.

Deklarace příkazu v Commands.Vsct

Příkazy nabídky jsou deklarovány v DslPackage\Commands.vsct. Tyto definice určují popisky položek nabídky a jejich umístění v nabídkách.

Soubor, který upravujete, Commands.vsct, importuje definice z několika souborů .h, které jsou umístěny v adresáři Instalační cesta sady Visual Studio SDK\VisualStudioIntegration\Common\Inc. Zahrnuje také GeneratedVsct.vsct, který je generován z vaší definice DSL.

Další informace o souborech .vsct najdete v tématu Tabulka příkazů sady Visual Studio (. Vsct) Soubory.

Přidání příkazu

  1. V Průzkumník řešení v rámci projektu DslPackage otevřete Příkazy.vsct.

  2. V elementu Commands definujte jedno nebo více tlačítek a skupinu. Tlačítko je položka v nabídce. Skupina je oddíl v nabídce. Chcete-li definovat tyto položky, přidejte následující prvky:

    <!-- 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>
    

    Poznámka:

    Každé tlačítko nebo skupina jsou identifikovány identifikátorem GUID a celočíselnou ID. Můžete vytvořit několik skupin a tlačítek se stejným identifikátorem GUID. Musí ale mít jiná ID. Názvy GUID a ID se překládají na skutečné identifikátory GUID a číselná ID v <Symbols> uzlu.

  3. Přidejte omezení viditelnosti pro příkaz, aby se načetlo pouze v kontextu jazyka specifického pro vaši doménu. Další informace naleznete v tématu VisibilityConstraints – element.

    Chcete-li to provést, přidejte následující prvky do elementu CommandTable Commands za element.

    <VisibilityConstraints>
      <!-- Ensures the command is only loaded for this DSL -->
      <VisibilityItem guid="guidCustomMenuCmdSet" id="cmdidMyContextMenuCommand"
        context="guidEditor"/>
    </VisibilityConstraints>
    
  4. Definujte názvy, které jste použili pro identifikátory GUID a ID. Uděláte to tak, že za element přidáte Symbols prvek CommandTable do elementu Commands .

    <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>
    
  5. Nahraďte {000...000} identifikátorEM GUID, který identifikuje vaše skupiny a položky nabídky. Pokud chcete získat nový identifikátor GUID, použijte nástroj Vytvořit identifikátor GUID v nabídce Nástroje .

    Poznámka:

    Pokud přidáte další skupiny nebo položky nabídky, můžete použít stejný identifikátor GUID. Je však nutné použít nové hodnoty pro IDSymbols.

  6. V kódu, který jste zkopírovali z tohoto postupu, nahraďte každý výskyt následujících řetězců vlastními řetězci:

    • grpidMyMenuGroup

    • cmdidMyContextMenuCommand

    • guidCustomMenuCmdSet

    • My Context Menu Command

Aktualizace verze balíčku v Package.tt

Pokaždé, když přidáte nebo změníte příkaz, před vydáním nové verze jazyka specifického pro doménu aktualizujte version parametr použitého ProvideMenuResourceAttribute u třídy balíčku.

Protože třída balíčku je definována ve vygenerovaném souboru, aktualizujte atribut v textovém souboru šablony, který generuje soubor Package.cs.

Aktualizace souboru Package.tt

  1. V Průzkumník řešení otevřete v projektu DslPackage ve složce GeneratedCode soubor Package.tt.

  2. ProvideMenuResource Vyhledejte atribut.

  3. Zvýší version parametr atributu, což je druhý parametr. Pokud chcete, můžete název parametru napsat explicitně, aby vám připomínal jeho účel. Příklad:

    [VSShell::ProvideMenuResource("1000.ctmenu", version: 2 )]

Definování chování příkazu

Vaše DSL již obsahuje některé příkazy, které jsou implementovány v částečné třídě, která je deklarována v DslPackage\GeneratedCode\CommandSet.cs. Chcete-li přidat nové příkazy, musíte tuto třídu rozšířit vytvořením nového souboru, který obsahuje částečnou deklaraci stejné třídy. Název třídy je obvykle YourDslName>CommandSet.< Je užitečné začít ověřením názvu třídy a kontrolou jejího obsahu.

Třída sady příkazů je odvozena z CommandSet.

Rozšíření třídy CommandSet

  1. V Průzkumník řešení v projektu DslPackage otevřete složku GeneratedCode a pak se podívejte do CommandSet.tt a otevřete jeho vygenerovaný soubor CommandSet.cs. Poznamenejte si obor názvů a název první třídy, která je tam definována. Může se například zobrazit:

    namespace Company.Language1

    { ... internal partial class Language1CommandSet : ...

  2. V DslPackage vytvořte složku s názvem Custom Code. V této složce vytvořte nový soubor třídy s názvem CommandSet.cs.

  3. V novém souboru zapište částečnou deklaraci, která má stejný obor názvů a název jako vygenerovaná částečná třída. Příklad:

    namespace Company.Language1 /* Make sure this is correct */

    { internal partial class Language1CommandSet { ...

    Poznámka:

    Pokud jste k vytvoření nového souboru použili šablonu třídy, musíte opravit obor názvů i název třídy.

Kód sady příkazů bude obvykle muset importovat následující obory názvů:

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;

Upravte obor názvů a název třídy tak, aby odpovídaly názvům vygenerovaným commandSet.cs:

namespace Company.Language1 /* Make sure this is correct */
{
  // Same class as the generated class.
  internal partial class Language1CommandSet
  {

Je nutné definovat dvě metody, jednu pro určení, kdy bude příkaz viditelný v místní nabídce (místní) a druhý k provedení příkazu. Tyto metody nejsou přepsány; místo toho je zaregistrujete v seznamu příkazů.

Definujte, kdy bude příkaz viditelný.

Pro každý příkaz definujte metodu OnStatus... , která určuje, jestli se příkaz zobrazí v nabídce a jestli bude povolený nebo zašedlý. Visible Nastavte a Enabled vlastnosti objektu MenuCommand, jak je znázorněno v následujícím příkladu. Tato metoda se volá, aby se vytvořila místní nabídka pokaždé, když uživatel klikne pravým tlačítkem myši na diagram, takže musí rychle fungovat.

V tomto příkladu je příkaz viditelný pouze v případě, že uživatel vybral určitý typ obrazce a je povolen pouze v případě, že alespoň jeden z vybraných prvků je v určitém stavu. Příklad je založen na šabloně DSL diagramu tříd a ClassShape a ModelClass jsou typy, které jsou definovány v DSL:

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
} } } }

Následující fragmenty jsou často užitečné v metodách OnStatus:

  • this.CurrentSelection. Obrazec, na který uživatel klikl pravým tlačítkem, je vždy součástí tohoto seznamu. Pokud uživatel klikne na prázdnou část diagramu, je diagram jediným členem seznamu.

  • this.IsDiagramSelected() - true pokud uživatel kliknul na prázdnou část diagramu.

  • this.IsCurrentDiagramEmpty()

  • this.IsSingleSelection() – uživatel nevybere více objektů.

  • this.SingleSelection – obrazec nebo diagram, na který uživatel klikl pravým tlačítkem

  • shape.ModelElement as MyLanguageElement – prvek modelu reprezentovaný obrazcem.

Obecně platí, že Visible vlastnost závisí na tom, co je vybráno, a vlastnost Enabled závisí na stavu vybraných prvků.

Metoda OnStatus by neměla měnit stav Storu.

Definování toho, co příkaz dělá

Pro každý příkaz definujte metodu OnMenu... , která provede požadovanou akci, když uživatel klikne na příkaz nabídky.

Pokud provedete změny prvků modelu, musíte to udělat uvnitř transakce. Další informace naleznete v tématu Postupy: Úprava standardního příkazu nabídky.

V tomto příkladu , ClassShapeModelClassa Comment jsou typy, které jsou definovány v DSL, který je odvozen z diagramu tříd DSL šablony.

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!
  }
}

Další informace o tom, jak v modelu přejít z objektu na objekt a jak vytvořit objekty a odkazy, naleznete v tématu Postupy: Úprava standardního příkazu nabídky.

Registrace příkazu

Opakujte v jazyce C# deklarace hodnot GUID a ID, které jste vytvořili v části Symboly CommandSet.vsct:

private Guid guidCustomMenuCmdSet =
    new Guid("00000000-0000-0000-0000-000000000000");
private const int grpidMyMenuGroup = 0x01001;
private const int cmdidMyContextMenuCommand = 1;

Použijte stejnou hodnotu GUID, jakou jste vložili do commands.vsct.

Poznámka:

Pokud změníte část Symboly v souboru VSCT, musíte také změnit tyto deklarace tak, aby odpovídaly. Měli byste také zvýšit číslo verze v Package.tt

Zaregistrujte příkazy nabídky jako součást této sady příkazů. GetMenuCommands() při inicializaci diagramu se volá jednou:

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;
}

Otestování příkazu

Sestavte a spusťte DSL v experimentální instanci sady Visual Studio. Příkaz by se měl zobrazit v místní nabídce v situacích, které jste zadali.

Cvičení příkazu

  1. Na panelu nástrojů Průzkumník řešení klikněte na Transformovat všechny šablony.

  2. Stisknutím klávesy F5 znovu sestavíte řešení a spustíte ladění jazyka specifického pro doménu v experimentálním sestavení.

  3. V experimentálním sestavení otevřete ukázkový diagram.

  4. Kliknutím pravým tlačítkem myši na různé položky v diagramu ověřte, že je příkaz správně povolený nebo zakázaný, a v závislosti na vybrané položce se správně zobrazí nebo skryje.

Odstraňování potíží

Příkaz se nezobrazuje v nabídce:

  • Příkaz se zobrazí pouze v instancích ladění sady Visual Studio, dokud nenainstalujete balíček DSL. Další informace najdete v tématu Nasazení jazykových řešení specifických pro doménu.

  • Ujistěte se, že vaše experimentální ukázka má správnou příponu názvu souboru pro tuto DSL. Pokud chcete zkontrolovat příponu názvu souboru, otevřete DslDefinition.dsl v hlavní instanci sady Visual Studio. Potom v DSL Exploreru klepněte pravým tlačítkem myši na uzel Editor a potom klepněte na příkaz Vlastnosti. V okno Vlastnosti zkontrolujte FileExtension vlastnost.

  • Zvýšíte číslo verze balíčku?

  • Nastavte zarážku na začátku metody OnStatus. Když kliknete pravým tlačítkem myši na libovolnou část diagramu, měla by se přerušit.

OnStatus metoda není volána:

  • Ujistěte se, že identifikátory GUID a ID v kódu CommandSet odpovídají identifikátorům GUID v části Symboly v části Commands.vsct.

  • V nástroji Commands.vsct se ujistěte, že identifikátor GUID a ID v každém nadřazeném uzlu identifikuje správnou nadřazenou skupinu.

  • Do příkazového řádku sady Visual Studio zadejte devenv /rootsuffix exp /setup. Potom restartujte instanci ladění sady Visual Studio.

  • Projděte si metodu OnStatus a ověřte tento příkaz. Viditelné a příkazy. Povoleno je nastaveno na hodnotu true.

Zobrazí se nesprávný text nabídky nebo se příkaz zobrazí na nesprávném místě:

  • Ujistěte se, že kombinace identifikátoru GUID a ID je pro tento příkaz jedinečná.

  • Ujistěte se, že jste odinstalovali starší verze balíčku.

Poznámka:

Komponenta Transformace textové šablony se automaticky nainstaluje jako součást sady funkcí vývoje rozšíření sady Visual Studio. Můžete ho také nainstalovat z karty Jednotlivé komponenty Instalační program pro Visual Studio v kategorii sad SDK, knihoven a architektur. Nainstalujte komponentu Modeling SDK z karty Jednotlivé komponenty .