A-Sharabiani
A-Sharabiani

Reputation: 19377

How to customize the context menu in the solution explorer for a specific project type?

Description


I have developed a Visual Studio extension (VSPackage) which adds a new Project Type to Visual Studio (using CPS Project System). I also have added some Commands to the VSPackage.

When right clicking on my Project Node in the Solution Explorer, I want to have a customized context menu to appear.

Example


For example: in the screen shot below, I want to get rid of the Build command and add a custom command (e.x. mycommand).

enter image description here

I tried..


Setting the Parent of my custom command to IDM_VS_CTXT_PROJNODE.

Question


Upvotes: 5

Views: 2597

Answers (2)

awoosnam
awoosnam

Reputation: 91

I'm not sure about removing the existing Build menu item... but as for having context menu items appear only when right-clicking on your custom project type, <VisibilityConstraints> might help:

(Excerpt from an example usage):

Often a package is being loaded to run a BeforeQueryStatus method for a button to determine its visibility. With <VisibilityConstraints> we can determine the visibility of a button without running BeforeQueryStatus and therefore don't need to load the package before the user clicks the button.

I've only ever used this strategy to show menu items for specific file types, but there are also some term types related to projects that might be more useful for this scenario.

Upvotes: 0

sboulema
sboulema

Reputation: 836

You were close with the IDM_VS_CTXT_PROJNODE parent.

Here is how I achieved it in my FluentMigratorRunner extension, which only shows its context menu item for a project if it has a reference to the FluentMigrator NuGet package.

Step 1: Add a submenu to the context menu

<Menus>
  <Menu guid="guidCmdSet" id="packageMenu" priority="0x0300" type="Menu">
    <Parent guid="guidSHLMainMenu" id="IDG_VS_CTXT_PROJECT_BUILD" />
    <CommandFlag>DynamicVisibility</CommandFlag>
    <CommandFlag>DefaultInvisible</CommandFlag>
    <Strings>
      <ButtonText>CPSProject</ButtonText>
      <CommandName>CPSProject</CommandName>
    </Strings>
  </Menu>

Note the added special CommandFlag elements.

Step 2: Add a group to the menu

<Groups>  
  <Group guid="guidCmdSet" id="packageMenuGroup" priority="0x0600">
    <Parent guid="guidCmdSet" id="packageMenu" />
  </Group>    
</Groups>

Step 3: Add a button

  <Button guid="guidCmdSet" id="specialBuildActionId" priority="0x0100" type="Button">
    <Parent guid="guidCmdSet" id="packageMenuGroup" />
    <CommandFlag>DynamicVisibility</CommandFlag>
    <Strings>
      <ButtonText>Special build</ButtonText>
    </Strings>

Step 4: Add the menu in your *Package.cs

protected override async System.Threading.Tasks.Task InitializeAsync(System.Threading.CancellationToken cancellationToken, IProgress<ServiceProgressData> progress)
{
    // Initialize the Fluent Migrator Menu, should only be visible for projects with FluentMigrator reference
    var mcs = await GetServiceAsync(typeof(IMenuCommandService)) as OleMenuCommandService;
    var menuCommandId = new CommandID(packageCmdSetGuidString, 0x1010);
    var menuItem = new OleMenuCommand(null, menuCommandId);
    menuItem.BeforeQueryStatus += MenuItem_BeforeQueryStatus;

    mcs.AddCommand(menuItem);
}

private void MenuItem_BeforeQueryStatus(object sender, EventArgs e) =>
    ((OleMenuCommand)sender).Visible = ???;

Note the added BeforeQueryStatus eventhandler.

In that eventhandler you can check the type of the project and return a boolean controlling if the extra context menu should be shown yes or no

Upvotes: 4

Related Questions