功能表和工具列概觀

功能表和工具列是使用者存取擴充功能中命令的方式。 它們是一種圖形方式,方便向使用者呈現您的命令。 通常,相關的命令會一起聚集在相同的功能表或工具列上。

使用功能表和工具列

本概觀涵蓋使用功能表和工具列的這些主要案例:

建立功能表

若要使用新的擴充性模型建立功能表,請新增靜態 MenuConfiguration 屬性,以 VisualStudioContribution 屬性裝飾類別。 此靜態屬性可以放置在 [擴充功能] 專案中的任何類別上。 在新的 [擴充性模型] 範例中,為了簡化,它們存在於 Extension 類別上。 UI 中不會顯示任何可見子系的功能表。

[VisualStudioContribution]
public class ExtensionEntrypoint : Extension
{
  [VisualStudioContribution]
  public static MenuConfiguration MyMenu => new("%MyMenu.DisplayName%");
}

MenuConfiguration 類別有一些您應該熟悉的參數:

參數 類型​ 必要 描述
DisplayName String Yes 功能表的預設顯示名稱。 以「%」字元括住此字串,以將本字串當地語系化。 請參閱當地語系化中繼資料
TooltipText String No 當功能表懸停或聚焦時要顯示為工具提示的文字。 以「%」字元括住此字串,以將本字串當地語系化。 請參閱當地語系化中繼資料
位置 CommandPlacement[] No 指定 Visual Studio 中功能表將成為其上層的現有 [群組]。 請參閱在 IDE 中放置功能表
子系 MenuChild[] No 描述了應該作為此功能表上層的一組命令、功能表和群組。 這些項目在陣列中定義的順序代表它們在 IDE 中直觀顯示的順序。 請參閱 將項目放置在功能表上

在 IDE 中放置功能表

功能表與命令放置在 IDE 中的方式相同。 請參閱 在 IDE 中放置命令

public override MenuConfiguration MyMenu => new("%MyMenu.DisplayName%")
{
    Placements = new CommandPlacement[]
    {
        CommandPlacement.KnownPlacements.ToolsMenu
    },
};

將項目放置在功能表上

透過將項目新增至 MenuConfiguration 上的 Children 陣列,完成將項目放置在功能表上。 項目新增至此陣列的順序會決定這些項目在 IDE 中直觀顯示的方式。

將命令放置在功能表上

使用 MenuChild.Command<T> 方法將命令放置在功能表上,以 Command 的類別名稱取代範本引數。

[VisualStudioContribution]
public static MenuConfiguration MyMenu => new("%MyMenu.DisplayName%")
{
    Children = new[]
    {
        MenuChild.Command<MyCommand>(),
    },
};

將功能表放置在功能表上

將功能表放置在功能表上是使用 MenuChild.Menu 方法完成的,並傳入另一 MenuConfiguration 個做為參數。

[VisualStudioContribution]
public static MenuConfiguration MyChildMenu => new("My Child Menu!");

[VisualStudioContribution]
public static MenuConfiguration MyParentMenu => new("My Parent Menu!")
{
    Children = new[]
    {
        MenuChild.Menu(MyChildMenu),
    },
};

將功能表項目分成群組

功能表中的項目可以通過在項目之間加入 MenuChild.Separator 來進行分組。 從視覺上看,這看起來像放置在兩個項目之間的細線。

[VisualStudioContribution]
public static MenuConfiguration MyMenu1 => new("%MyMenu.DisplayName%")
{
    Children = new[]
    {
        MenuChild.Command<MyCommand1>(), // Assuming there is a `Command` defined in the extension called `MyCommand1`
        MenuChild.Menu(MyMenu2), // Assuming there is a `MenuConfiguration` defined in the extension called `MyMenu2`
        MenuChild.Separator,
        MenuChild.Command<MyCommand2>(), // Assuming there is a `Command` defined in the extension called `MyCommand2`
        MenuChild.Menu(MyMenu3), // Assuming there is a `MenuConfiguration` defined in the extension called `MyMenu3`
    },
};

這也可以透過使用 MenuChild.Group 方法來定義群組內嵌來完成。 接著,您會使用 GroupChild 類別將項目放置到群組的上層。

[VisualStudioContribution]
public static MenuConfiguration MyMenu1 => new("%MyMenu.DisplayName%")
{
    Children = new[]
    {
        MenuChild.Group(
            GroupChild.Command<MyCommand1>(), // Assuming there is a `Command` defined in the extension called `MyCommand1`
            GroupChild.Menu(MyMenu2)), // Assuming there is a `MenuConfiguration` defined in the extension called `MyMenu2`
        MenuChild.Group(
            GroupChild.Command<MyCommand2>(), // Assuming there is a `Command` defined in the extension called `MyCommand2`
            GroupChild.Menu(MyMenu3)), // Assuming there is a `MenuConfiguration` defined in the extension called `MyMenu3`
    },
};

在前面的兩個範例中,IDE 中產生的功能表是相同的。 功能表 MyMenu1 看起來會像下列螢幕擷取畫面中的功能表:

Screenshot of menu with separator.

建立工具列

若要使用新的 [擴充性模型] 建立功具列,請新增靜態 ToolbarConfiguration 屬性,以 VisualStudioContribution 屬性裝飾類別。 此靜態屬性可以放置在 [擴充功能] 專案中的任何類別上。 在新的 [擴充性模型] 範例中,為了簡化,它們存在於 Extension 類別上。

[VisualStudioContribution]
public class ExtensionEntrypoint : Extension
{
  [VisualStudioContribution]
  public static ToolbarConfiguration MyToolbar => new("%MyToolbar.DisplayName%");
}

ToolbarConfigurationPlacement 屬性保留為 null,會將工具列放置在 [標準工具列] 列上,並可在 View -> Toolbars 功能表中選取工具列來顯示。

ToolbarConfiguration 類別

ToolbarConfiguration 類別有一些您應該熟悉的屬性:

屬性 型別 必要 描述
DisplayName String Yes 工具列的預設顯示名稱。 以「%」字元括住此字串,以將本字串當地語系化。 請參閱當地語系化中繼資料
TooltipText String No 當工具列懸停或聚焦時要顯示為工具提示的文字。 以「%」字元括住此字串,以將本字串當地語系化。 請參閱當地語系化中繼資料
位置 CommandPlacement[] No 指定 Visual Studio 中工具列將成為其上層的現有 [群組]。 請參閱在 IDE 中放置命令。 將此屬性保留為 null,會將工具列放置在 [標準工具列] 列上,並可在 View -> Toolbars 功能表中選取工具列來顯示。
子系 ToolbarChild[] No 描述了應該作為此工具列上層的一組命令、功能表和群組。 這些項目在陣列中定義的順序代表它們在 IDE 中直觀顯示的順序。 請參閱將項目放置在工具列上

將項目放置在工具列上

使用 ToolbarChild.Command<T> 方法將命令放置在工具列上,以 Command 的類別名稱取代範本引數。

[VisualStudioContribution]
public static ToolbarConfiguration MyToolbar => new("%MyToolbar.DisplayName%")
{
    Children = new[]
    {
        ToolbarChild.Command<MyCommand>(),
    },
};

將工具列項目分成群組

工具列中的項目可以通過在項目之間加入 ToolbarChild.Separator 來進行分組。 從視覺上看,這看起來像放置在兩個項目之間的細線。

[VisualStudioContribution]
public static ToolbarConfiguration MyToolbar => new("%MyToolbar.DisplayName%")
{
    Children = new[]
    {
        ToolbarChild.Command<MyCommand1>(), // Assuming there is a `Command` defined in the extension called `MyCommand1`
        ToolbarChild.Separator,
        ToolbarChild.Command<MyCommand2>(), // Assuming there is a `Command` defined in the extension called `MyCommand2`
    },
};

這也可以透過使用 ToolbarChild.Group 方法來定義群組內嵌來完成。 接著,您會使用 ToolbarChild 類別將項目放置到群組的上層。

[VisualStudioContribution]
public static ToolbarConfiguration MyToolbar => new("%MyToolbar.DisplayName%")
{
    Children = new[]
    {
        ToolbarChild.Group(
            GroupChild.Command<MyCommand1>(), // Assuming there is a `Command` defined in the extension called `MyCommand1`
        ToolbarChild.Group(
            GroupChild.Command<MyCommand2>(), // Assuming there is a `Command` defined in the extension called `MyCommand2`
    },
};

在此處的兩個範例中,IDE 中產生的工具列是相同的。 工具列 MyToolbar 看起來會像下列螢幕擷取畫面中的工具列 :

Screenshot of a toolbar with separator.

建立群組

群組是項目的視覺分組,其中分隔符會放置在相鄰群組的最後一個項目與第一個項目之間。 在上述各節中,說明如何在 MenuConfigurationToolbarConfigurationChildren 屬性的內容中建立群組。 您也可以在自己的 CommandGroupConfiguration 內定義群組。 當您想要在 Visual Studio 中將群組放置在現有功能表或工具列的上層,而不需定義您自己的功能表或工具列時,這會很有用。 如果您想要以將群組定義與功能表和工具列定義分開的方式來格式化程式碼,它也很有用。

若要使用新的 [擴充性模型] 建立群組,請新增靜態 CommandGroupConfiguration 屬性。 此靜態屬性可以放置在 [擴充功能] 專案中的任何類別上。 在新的 [擴充性模型] 範例中,為了簡化,它們存在於 Extension 類別上。 如果 CommandGroupConfiguration 指定 Placement,它也應該使用 VisualStudioContribution 屬性裝飾。

public static CommandGroupConfiguration MyGroup => new();

[VisualStudioContribution]
private static CommandGroupConfiguration MyGroupWithPlacement => new(GroupPlacement.KnownPlacements.ToolsMenu);

CommandGroupConfiguration 類別

CommandGroupConfiguration 類別有一些您應該熟悉的參數:

參數 類型​ 必要 描述
放置 GroupPlacement No 指定 Visual Studio 中群組將成為其上層的現有功能表或工具列。 請參閱在 IDE 中放置群組
子系 GroupChild[] No 描述了應該作為此群組上層的一組命令和功能表。 這些項目在陣列中定義的順序代表它們在 IDE 中直觀顯示的順序。 請參閱將項目放置在群組上

將群組放置在 IDE 中

Visual Studio 中有一組定義完善的位置,可以在其中放置命令。 這些位置是由類別 Commands.GroupPlacement 上的屬性 CommandPlacement.KnownPlacements 所定義。 KnownPlacements 的目前集合是:

  • ToolsMenu - 命令會放置在 Visual Studio 最上層 [工具] 功能表下的群組中。
  • ViewOtherWindowsMenu - 命令會放置在最上層 [檢視] -> Visual Studio 中的 [其他視窗] 功能表之下的群組中。
  • ExtensionsMenu - 命令會放置在 Visual Studio 最上層 [擴充功能] 功能表下的群組中。
[VisualStudioContribution]
public static CommandGroupConfiguration MyGroup1 => new(GroupPlacement.KnownPlacements.ToolsMenu);

[VisualStudioContribution]
public static CommandGroupConfiguration MyGroup2 => new(GroupPlacement.KnownPlacements.ExtensionsMenu.WithPriority(0x100));

將項目放置在群組上

您可以使用 CommandGroupConfiguration 上的 Children 陣列屬性,將命令和功能表放置在群組上 。

將命令放置在群組上

使用 GroupChild.Command<T> 方法將命令放置在群組上,以 Command 的類別名稱取代範本引數。

[VisualStudioContribution]
public static CommandGroupConfiguration MyGroup => new(GroupPlacement.KnownPlacements.ToolsMenu)
{
    Children = new[]
    {
        GroupChild.Command<MyCommand>(),
    },
};

將功能表放置在群組上

將功能表放置在群組上是使用 GroupChild.Menu 方法完成的,並傳入另一 MenuConfiguration 個做為參數。

[VisualStudioContribution]
public static MenuConfiguration MyMenu => new("%MyMenu.DisplayName%");

[VisualStudioContribution]
public static CommandGroupConfiguration MyGroup => new(GroupPlacement.KnownPlacements.ToolsMenu)
{
    Children = new[]
    {
        GroupChild.Menu(MyMenu),
    },
};

將群組放置在功能表或工具列上

將群組放置在功能表上是使用 MenuChild.Group 方法完成的,並傳入另一 CommandGroupConfiguration 個做為參數。 將群組放置在功具列上是使用 ToolbarChild.Group 方法完成的,並傳入另一 CommandGroupConfiguration 個做為參數。 以這種方式將群組放置到功能表或工具列的上層,不能將 CommandGroupConfigurationPlacement 屬性設定為除了 null 以外的任何值,而且不應該使用 VisualStudioContribution 屬性裝飾。

private static CommandGroupConfiguration MyGroup => new()
{
    Children = new[]
    {
        GroupChild.Command<MyCommand1>(), // Assuming there is a `Command` defined in the extension called `MyCommand1`
        GroupChild.Command<MyCommand2>(), // Assuming there is a `Command` defined in the extension called `MyCommand2`
    },
};

[VisualStudioContribution]
public static MenuConfiguration MyMenu => new("%MyMenu.DisplayName%")
{
    Children = new[]
    {
        MenuChild.Group(MyGroup),
    },
};
private static CommandGroupConfiguration MyGroup => new()
{
    Children = new[]
    {
        GroupChild.Command<MyCommand1>(), // Assuming there is a `Command` defined in the extension called `MyCommand1`
        GroupChild.Command<MyCommand2>(), // Assuming there is a `Command` defined in the extension called `MyCommand2`
    },
}

[VisualStudioContribution]
public static ToolbarConfiguration MyToolbar => new("%MyToolbar.DisplayName%")
{
    Children = new[]
    {
        ToolbarChild.Group(MyGroup),
    },
};

放置順序 (優先順序)

當放置到 VSCT 中,相對於放置到相同群組、功能表或工具列上層的其他項目所定義的控制項的上層時,位置會根據其 Priority 屬性的值來排序。 Priority 屬性為 unsigned shortCommandPlacementGroupPlacement 的預設 Priority 值為 0,而且可以藉由呼叫 CommandPlacement.WithPriorityGroupPlacement.WithPriority 方法來修改,並傳入所需的 Priority 值。 Priority 也可以使用 CommandPlacement.VsctParentGroupPlacement.VsctParent 方法來設定,並直接傳入所需的 Priority

當使用 VisualStudio.Extensibility 模型將項目設定為透過組態物件定義的控制項時,不會牽涉到 Priority 屬性 (即,放置為上層的群組、功能表或工具列是使用 CommandGroupConfigurationMenuConfiguration,或 ToolbarConfiguration 定義的)。

GroupPlacement

GroupPlacement.KnownPlacements.ToolsMenu.WithPriority(0x0500);
// Parenting a group to the "Help" top level menu
GroupPlacement.VsctParent(new Guid("{d309f791-903f-11d0-9efc-00a0c911004f}"), id: 0x0088, priority: 0x0500);

CommandPlacement

CommandPlacement.KnownPlacements.ToolsMenu.WithPriority(0x0500);
// Parenting a command to the "Help -> About" group
CommandPlacement.VsctParent(new Guid("{d309f791-903f-11d0-9efc-00a0c911004f}"), id: 0x016B, priority: 0x0801);