共用方式為


HOW TO:在捷徑功能表中加入命令

您可以將功能表命令加入您定義域專屬語言 (DSL),讓您的使用者可以執行專屬於您的 DSL 的工作。 當使用者以滑鼠右鍵按一下圖表上的內容 (捷徑)] 功能表中會顯示的指令。 使其只出現在功能表中,在特定情況下,您可以定義命令。 比方說,您可以顯示命令只有在使用者按一下特定類型的項目或處於特定狀態的項目時,才。

在 [摘要] 會執行步驟 DslPackage 的專案中,如下所示:

  1. 宣告在 Commands.vsct 中的指令

  2. 更新封裝的版本號碼,在 Package.tt。 您不必這麼做,每當您更改 Commands.vsct

  3. CommandSet 類別中撰寫方法顯現的命令,並定義您想要執行的命令。

如範例中,請參閱視覺化和模型的 SDK 網站。

注意事項注意事項

您也可以覆寫 CommandSet.cs 的方法,以修改某些現有的命令,例如 [剪下、 貼上、 全選],並列印的行為。如需詳細資訊,請參閱 HOW TO:使用網域指定的語言修改標準功能表命令

定義使用 MEF 命令

受管理的延伸架構 (MEF) 提供一個替代方法是定義在 [圖表] 功能表上的功能表命令。 它主要目的是讓 DSL 而將被您或者其他廠商延伸。 使用者可以選擇安裝只需 DSL,或可以安裝 DSL 和擴充功能。 不過,MEF 也會減少定義快顯功能表指令,在初期工作時若要啟用的 DSL 的 MEF 後的工作。

本主題中,如果使用方法:

  1. 您想要定義以外,用滑鼠右鍵按一下快顯功能表的功能表上的功能表命令。

  2. 您想要在功能表定義的命令的特定群組化。

  3. 您不想讓別人擴充 DSL 與他們自己的命令。

  4. 只想要定義一個指令。

否則,請考慮使用 MEF 方法,以定義命令。 如需詳細資訊,請參閱 使用 MEF 擴充您的 DSL

宣告在 Commands.Vsct 中的指令

功能表命令會在 DslPackage\Commands.vsct 中宣告。 這些定義指定了標籤的功能表項目和它們出現在功能表上的位置。

從數個放置在目錄中的.h 檔案的檔案進行編輯,Commands.vsct,匯入的定義 Visual Studio 的 SDK 安裝路徑\VisualStudioIntegration\Common\Inc。 它也包含了 GeneratedVsct.vsct,從您的 DSL 定義產生的。

如需有關.vsct 檔案的詳細資訊,請參閱Visual Studio 命令表裡 (。Vsct) 檔案

若要新增命令

  1. 方案總管] 中DslPackage 專案,請開啟 Commands.vsct。

  2. 在Commands項目,定義一或多個按鈕和群組。 A 按鈕是在功能表上的項目。 A 群組便會出現在功能表中的區段。 若要定義這些項目,請加入下列項目:

    <!-- 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>
    
    注意事項注意事項

    每一個按鈕或群組識別是根據 GUID 和一個整數 id。您可以建立數個群組和按鈕具有相同的 GUID。不過,它們必須有不同的 Id。GUID 名稱與識別碼名稱會轉譯為實際的 Guid 和數值 Id <Symbols> 節點。

  3. 將命令的可見性條件約束,就會載入定義域專屬語言內容中。 如需詳細資訊,請參閱 VisibilityConstraints 項目

    若要這樣做,新增下列項目,在CommandTable後的項目Commands項目。

    <VisibilityConstraints>
      <!-- Ensures the command is only loaded for this DSL -->
      <VisibilityItem guid="guidCustomMenuCmdSet" id="cmdidMyContextMenuCommand"
        context="guidEditor"/>
    </VisibilityConstraints>
    
  4. 定義您所使用的 guid 及識別碼的名稱。 若要這樣做,請將Symbols中的項目CommandTable後的項目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. 取代{000...000}以 GUID 來識別您的群組和功能表項目。 若要取得新的 GUID,請使用建立 GUID 工具在工具功能表。

    注意事項注意事項

    如果您新增更多的群組或功能表項目,您可以使用相同的 GUID。不過,您必須使用新的值,如IDSymbols。

  6. 在您有複製此程序中的程式碼,取代出現下列字串的每個使用您自己的字串:

    • grpidMyMenuGroup

    • cmdidMyContextMenuCommand

    • guidCustomMenuCmdSet

    • 我的內容功能表命令

更新套件中的版本 Package.tt

每當您新增或變更的指令,請更新version參數的ProvideMenuResourceAttribute ,適用於封裝類別之後,再放開您的網域特定語言的新版本。

封裝類別定義中產生的檔案,因為更新會產生 Package.cs 檔文字範本檔案中的屬性。

若要更新的 Package.tt 檔案

  1. 方案總管] 中,請在 DslPackage 專案、 在 GeneratedCode 資料夾中,開啟 Package.tt 檔案。

  2. 找出ProvideMenuResource屬性。

  3. 遞增值version屬性,也就是第二個參數的參數。 如果您想要的選項,您可以撰寫明確要提醒您它的用途的參數名稱。 例如:

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

定義命令的行為

您的 DSL 已經在 DslPackage\GeneratedCode\CommandSet.cs 中宣告的部分類別中實作某些命令。 若要新增新的命令,您必須藉由建立新的檔案所在的相同類別的部分宣告擴充這個類別。 類別的名稱通常是 <YourDslName>CommandSet。 最好先驗證類別的名稱,然後檢查其內容。

命令的集合類別衍生自CommandSet

若要擴充的 CommandSet 類別

  1. 在 [方案總管] 中,在 DslPackage 專案中,開啟 [GeneratedCode] 資料夾,再看 CommandSet.tt 下,開啟其產生的檔案 CommandSet.cs。 附註的命名空間和類別名稱的第一個那里定義。 例如,您可能會看到:

    namespace Company.Language1

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

  2. DslPackage,建立名為自訂程式碼的資料夾。 在這個資料夾中,建立新的類別檔案,名為 CommandSet.cs。

  3. 在新的檔案中,撰寫的部分宣告有相同的命名空間和產生的部分類別的名稱。 例如:

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

    { internal partial class Language1CommandSet { ...

    附註如果您使用 [類別] 範本來建立新的檔案時,您必須更正命名空間和類別名稱。

Dd820681.collapse_all(zh-tw,VS.110).gif擴充設定命令類別

指令集的程式碼通常也需要匯入下列命名空間:

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;

調整的命名空間和類別名稱,以符合在產生 CommandSet.cs:

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

您必須定義兩種方法,我們判定時,就會在 [內容] 功能表中,並執行命令以另外的 [看得見。 這些方法都不覆寫。 相反地,進行註冊的命令清單中。

Dd820681.collapse_all(zh-tw,VS.110).gif定義時,就會看得見

針對每一個命令,定義OnStatus...方法,決定是否 「 命令會顯示在功能表中,及是否它將會啟用或灰色。 設定Visible和Enabled屬性的MenuCommand,如下列範例所示。 若要建構快顯功能表的使用者在它必須快速地運作,按一下滑鼠右鍵在圖表中,每次呼叫這個方法。

在這個範例中,只有在使用者選取特定類型的圖形,並僅當至少一個選取的項目處於特定狀態時,才會啟用時,會顯示命令。 此範例根據類別圖表 DSL 範本,而 ClassShape 和 ModelClass 是 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
} } } }

下列片段是經常用於 OnStatus 方法:

  • this.CurrentSelection. 使用者以滑鼠右鍵按一下圖形總是會預留這份清單中。 如果使用者按一下圖表的空白部分,圖表就會是清單的唯一的成員。

  • this.IsDiagramSelected() - true如果使用者按一下圖表的空白部分。

  • this.IsCurrentDiagramEmpty()

  • this.IsSingleSelection()-使用者沒有選取 [多個物件

  • this.SingleSelection-使用者用滑鼠右鍵按一下圖表的圖形

  • shape.ModelElement as MyLanguageElement-圖形所代表的模型項目。

一般來說,讓Visible屬性取決於選取的項目,並讓Enabled屬性取決於選取的項目狀態。

OnStatus 方法不應該變更的儲存區的狀態。

Dd820681.collapse_all(zh-tw,VS.110).gif定義命令的功用

針對每一個命令,定義OnMenu...方法,執行必要的動作,當使用者按一下功能表指令。

若您對模型元素的變更,您必須進行在交易內。 如需詳細資訊,請參閱 HOW TO:使用網域指定的語言修改標準功能表命令

在這個範例中, ClassShape, ModelClass,以及Comment都是衍生自類別圖表 DSL 範本 DSL 中所定義的型別。

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

如需有關如何在模型中,巡覽物件物件,以及有關如何建立物件和連結的詳細資訊,請參閱HOW TO:使用網域指定的語言修改標準功能表命令

Dd820681.collapse_all(zh-tw,VS.110).gif註冊命令

在 C# 中重複的 GUID 及識別碼值,在 CommandSet.vsct 中的 [符號] 區段中所做的宣告:

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

使用相同的 GUID 值,當您插入Commands.vsct

注意事項注意事項

如果您變更的 VSCT 檔案的 [符號] 區段,您也必須變更,使其符合這些宣告。您也應該增加 Package.tt 中的版本號碼

註冊功能表命令,這個命令集的一部分。 GetMenuCommands()一旦當圖表初始化呼叫:

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

測試的命令

建置並執行 DSL 實驗性質的 Visual Studio 執行個體中。 在快顯功能表,請在您所指定的情況下,會出現命令。

若要執行的命令

  1. 方案總管] 中 ] 工具列上,按一下 轉換所有的範本

  2. 按下 F5 來重建方案,並啟動偵錯實驗建置的定義域專屬語言。

  3. 在實驗性質的組建中,開啟的範例圖表。

  4. 以滑鼠右鍵按一下圖表中,以確認該命令正確啟用或停用,並適當地顯示或隱藏,取決於選取的項目中的各種項目。

疑難排解

命令沒有出現在功能表中:

  • 命令將只出現在偵錯的 Visual Studio 的執行個體,直到您安裝 DSL 封裝。 如需詳細資訊,請參閱 部署網域指定的語言方案

  • 請確定您實驗性的範例有正確的副檔名,如這個 DSL。 若要檢查檔案的副檔名,請開啟 DslDefinition.dsl Visual Studio 的主要執行個體中。 以滑鼠右鍵然後 DSL 總管] 中按一下 [編輯器] 節點,然後按一下 [內容。 在 [屬性] 視窗中,檢查 FileExtension 屬性。

  • 您是否遞增值的封裝版本號碼?

  • 您的 OnStatus 方法的開頭設定中斷點。 當您以滑鼠右鍵按一下圖表的任何部分上方時,它應該中斷。

    不會呼叫 OnStatus 方法

    • 請確定的 Guid 及識別碼 CommandSet 的程式碼中符合 Commands.vsct 的 [符號] 區段中。

    • 在 Commands.vsct,請確定的 GUID 及識別碼中的每個父節點識別正確的父群組。

    • 在 Visual Studio 的命令提示字元中,鍵入 devenv /rootsuffix exp /setup。 然後重新啟動偵錯的執行個體的 Visual Studio。

  • 逐步執行的 OnStatus 方法,以確認該指令。看得見和命令。啟用是設定為 true。

會出現 [錯誤] 功能表上的文字,或是指令是出現在錯誤的地方

  • 請確定這個命令所特有的 GUID 及識別碼的組合。

  • 請確定您已解除安裝舊版的封裝。

請參閱

概念

HOW TO:使用網域指定的語言修改標準功能表命令

其他資源

撰寫程式碼來自訂網域指定的語言

範例程式碼: 電路圖表