Resolved How do you get MainMenu or ContextMenu to show up in the VS ToolBox?

tim8w

Well-known member
Joined
Sep 8, 2020
Messages
131
Programming Experience
10+
I can get this to happen in code, but how do I get it to show up in the VisualStudios Toolbox?
 
Are you targeting .NET Framework 4.8, or .NET Core 3.x, or NET 5 ?
 
I don't use the WinForms Designer, so I don't know. I've not used it since VS2008. I was expecting to find them under the "Menus & Toolbars" group since that is where they used to be in old versions of Visual Studio. I suspect that they deliberately hid those controls in newer version of VS because they want you to use the forward compatible MenuString and ContextMenuString instead.
 
I don't use the WinForms Designer, so I don't know. I've not used it since VS2008. I was expecting to find them under the "Menus & Toolbars" group since that is where they used to be in old versions of Visual Studio. I suspect that they deliberately hid those controls in newer version of VS because they want you to use the forward compatible MenuString and ContextMenuString instead.
I am trying to use RadioCheck which is not available under the current menu system. I have a requirement to build a menu that has CheckBox or RadioButton along with a separate image. So I guess I'll do it in code then. Thanks!
 
I believe that the ToolStripMenuStrip has Checked property that you could use.
 
They were replaced with MenuStrip and ContextMenuStrip in .Net 2, in .Net 5 they have been removed. You can add other controls like RadioButton to strip by using ToolStripControlHost.
 
You can add other controls like RadioButton to strip by using ToolStripControlHost.
RadioButtons work as a group so I would assume that each ToolStripControlHost would be considered a single group. That means that you'll still have to add your own code to uncheck other items when an item is checked.
 
Here's a class I just created that may be of use to you:
ToolStripDropDownRadioCheckManager:
/// <summary>
/// Ensures that only one <see cref="ToolStripMenuItem"/> is checked at a time on a <see cref="System.Windows.Forms.ToolStripDropDown"/>
/// </summary>
public class ToolStripDropDownRadioCheckManager
{
    /// <summary>
    /// The <see cref="ToolStripDropDown"/> whose items should exhibit radio-check behaviour.
    /// </summary>
    private ToolStripDropDown _toolStripDropDown;

    /// <summary>
    /// Gets or sets the <see cref="ToolStripDropDown"/> whose items should exhibit radio-check behaviour.
    /// </summary>
    public ToolStripDropDown ToolStripDropDown
    {
        get => _toolStripDropDown;
        set
        {
            if (_toolStripDropDown != value)
            {
                if (_toolStripDropDown != null)
                {
                    // Remove event handler from old drop-down.
                    _toolStripDropDown.ItemClicked -= ToolStripDropDown_ItemClicked;
                }

                _toolStripDropDown = value;

                // Add event handler to new drop-down.
                _toolStripDropDown.ItemClicked += ToolStripDropDown_ItemClicked;
            }
        }
    }

    public ToolStripDropDownRadioCheckManager() { }

    public ToolStripDropDownRadioCheckManager(ToolStripDropDown toolStripDropDown)
    {
        this.ToolStripDropDown = toolStripDropDown;
    }

    private void ToolStripDropDown_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
    {
        if (e.ClickedItem is ToolStripMenuItem clickedItem &&
            clickedItem.CheckOnClick &&
            !clickedItem.Checked)
        {
            // The user has clicked an item that is not currently checked and will be checked automatically.

            // The get currently checked item, if there is one.
            var checkedMenuItem = ToolStripDropDown.Items
                                                   .OfType<ToolStripMenuItem>()
                                                   .SingleOrDefault(tsmi => tsmi.Checked);

            if (checkedMenuItem != null)
            {
                checkedMenuItem.Checked = false;
            }
        }
    }
}
It could certainly be improved but I'll leave that to you if you need it. It will work with both a ContextMenuStrip and a ToolStripMenuItem on a MenuStrip. All you have to do is make sure that CheckOnClick is true for each menu item and then create an instance and associate it appropriately. Here's the code I used to test it:
Sample Usage:
private ToolStripDropDownRadioCheckManager mainRadioCheckManager;
private ToolStripDropDownRadioCheckManager contextRadioCheckManager;

private void Form1_Load(object sender, EventArgs e)
{
    mainRadioCheckManager = new ToolStripDropDownRadioCheckManager(parentToolStripMenuItem.DropDown);
    contextRadioCheckManager = new ToolStripDropDownRadioCheckManager(contextMenuStrip1);
}
 
RadioButtons work as a group so I would assume that each ToolStripControlHost would be considered a single group. That means that you'll still have to add your own code to uncheck other items when an item is checked.
I just did a quick test, each DropDownItems collection is a separate radio group, as would be natural. That also goes for the root Items collections.
 
Back
Top Bottom