Thursday, March 31, 2011

Display the menu for a ToolStripDropDownButton as a context menu

I have a tool strip which contains a ToolStripDropDownButton. As an alternative access method, I would also like to be able to display this button's dropdown menu as a context menu, when the user right-clicks in the area below the tool strip.

I tried the following code, but it didn't work (it displayed the button's dropdown in the normal location, directly under the button):

Point contextMenuLocation = [get from WM_CONTEXTMENU]
myButton.DropDown.Show( contextMenuLocation );

The best idea I can think of would be to copy the toolstrip items from the button's dropdown into a ContextMenuStrip, but I don't see any simple way to do that (ToolStripItem does not implement ICloneable or a Clone method). Tool strip items store a reference to their Parent, so I can't just add the existing items to the context menu, as that would break the button.

Does anybody have a good idea on how to accomplish this?

From stackoverflow
  • A good way of populating two different dropdown with the same items is to extract the items creation into a function that builds the necessary drop down just before you open any instance of that dropdown. This also lets you enable a disable stuff if the application state changes.

    class A
    {
        public A()
        {
            button = new ToolStripDropDownButton();
            button.DropDown = new ToolStripDropDown();
    
            ToolStripDropDown dropDown = new ToolStripDropDown();
            dropDown.Opening += DropDownOpening;
            menu.Items.DropDown = dropDown;
    
        }
    
        void DropDownOpening(object sender, EventArgs e)
        {
            ToolStripDropDown dropDown = sender as ToolStripDropDown;
            if(dropDown != null) 
            {
                dropDown.Items.Clear();
                BuildMenu(dropDown);
            }
            else
            {
                // throw if you like
            }
        }
    
        void BuildMenu(ToolStripDropDown dropDown)
        {
            // TODO : Add items to dropdown
            // TODO : Take decisions depending on current application state
        }
    
        ToolStripDropDownButton button;
        MenuStrip menu;
    }
    
    Charlie : Thanks for the idea. I had thought of doing that, and I might end up going that way. I'm still interested to know if there's an easy way to do this without filling the menu dynamically, e.g. for cases where the menu is built via the designer.
    Charlie : I can't find any other good solution, so I think this is my best bet.

0 comments:

Post a Comment