简体   繁体   中英

Dynamic Visibility of menu item

In my VS extension I need to add menu item for my new project type. But I want it to show for my custom type only. So I added this code to.vcst file:

  <Button guid="_Interactive_WindowCmdSet" id="cmdidLoadUI" priority="0x0100" type="Button">
    <Parent guid="_Interactive_WindowCmdSet" id="ProjectItemMenuGroup" />
    <Icon guid="guidImages" id="bmpPic1" />
    <CommandFlag>DynamicVisibility</CommandFlag>
    <Strings>
      <ButtonText>Load</ButtonText>
    </Strings>
  </Button>


  <Group  guid="_Interactive_WindowCmdSet" id="ProjectItemMenuGroup" priority="0x0600">
    <Parent guid="guidSHLMainMenu" id="IDM_VS_CTXT_PROJNODE"/>
  </Group>

And added this code to package initialization:

            // Create the command for the menu item.
            CommandID projectMenuCommandID = new CommandID(GuidList.Interactive_WindowCmdSet, (int)PkgCmdIDList.cmdidLoadUI);
            OleMenuCommand projectmenuItem = new OleMenuCommand(LoadUIMenuItemCallback, projectMenuCommandID);
            projectmenuItem.BeforeQueryStatus += projectmenuItem_BeforeQueryStatus;
            mcs.AddCommand(projectmenuItem);

And query status handler is:

    private void projectmenuItem_BeforeQueryStatus(object sender, EventArgs e)
    {
        OleMenuCommand menuCommand = sender as OleMenuCommand;

        if (menuCommand != null)
            menuCommand.Visible = IsProjectOfRightType(GetSelected<Project>());
    }

The problem is - this status handler never get called. So I have this menu item showed for all project types.

I've tried also to implement IOleCommandTarget interface on my package, like:

    public int QueryStatus(ref Guid guidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText)
    {
        // Disable all commands in case if project is VisuaART project, otherwise - disable them.
        OLECMDF cmdf;

        for (int i = 0; i < cCmds; i++)
        {
            var command = prgCmds[i];
            if (command.cmdID == PkgCmdIDList.cmdidLoadUI)
            {
                if (IsProjectOfRightType(GetSelected<Project>()))
                    command.cmdf = (uint)COMMAND_SUPPORTED;
                else
                    command.cmdf = (uint)COMMAND_UNSUPPORTED;
            }

        }
        return VSConstants.S_OK;
    }

    private const OLECMDF COMMAND_SUPPORTED = OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED;
    private const OLECMDF COMMAND_UNSUPPORTED = OLECMDF.OLECMDF_INVISIBLE;

But that doesn't helped either. Method is called, but setting OLECMDF.OLECMDF_INVISIBLE does nothing. What should I do to hide this menu item for unsupported menu items?

Probably the problem is related with the load of the Package. To load the Package automatically just add this attribute to your Package Class:

[ProvideAutoLoad("f1536ef8-92ec-443c-9ed7-fdadf150da82")]

Ex.:

.
.
[ProvideAutoLoad("f1536ef8-92ec-443c-9ed7-fdadf150da82")]
public sealed class MyPackageTest : Package
{
.
.

When you don't add this attribute your class will be loaded just when you click on any button of your Package.

I hope I have helped.

In case it's applicable, Microsoft recommends using rule-based UI contexts when auto-loading packages:

Loading packages can have a performance impact and loading them sooner than needed is not the best practice. Visual Studio 2015 introduced the concept of Rules-based UI Contexts, a mechanism that allows extension authors to define the precise conditions under which a UI Context is activated and associated VSPackages are loaded.

I've only ever used this strategy to show menu items for specific file types (here's an example of how simple that can be), but there are also some term types related to projects that might be more useful for this scenario.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM