Question

I have a ToolStrip with multiple ToolStripDropDownButtons, each has a set of DropDownItems.

When the user clicks on an DropDownItem, the check mark is shown.

enter image description here

By default, multiple items can be clicked and therefore multiple check marks appear.

enter image description here

What I'm trying to do is when the user clicks one DropDownItem, the other already checked items should be unchecked. In other words, there should always be only one checked item in the DropDown list.

I've been dabbling with it for some time but I can't really figure out how to keep the current checked item as it is while uncheck other items.

Below is the code I have as of now.

private void subietm1ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            UncheckOtherToolStripMenuItems(sender);
        }

        public void UncheckOtherToolStripMenuItems(object selectedMenuItem)
        {
            List<ToolStripDropDownButton> dropdownButtons = new List<ToolStripDropDownButton>();
            foreach (ToolStripItem item in toolStrip1.Items)
            {
                if (item is ToolStripDropDownButton)
                {
                    dropdownButtons.Add((ToolStripDropDownButton)item);
                }
            }

            foreach (ToolStripDropDownButton btn in dropdownButtons)
            {
                foreach (ToolStripMenuItem d in btn.DropDownItems)
                {
                    if (d.Checked)
                        d.CheckState = CheckState.Unchecked;
                }
            }
        }

If someone could shed some light on this or tell me an easy way to go about it, I'd be grateful.

Thank you.

Was it helpful?

Solution

So easy...

Implement their method as described below:

    private void subietm1ToolStripMenuItem_Click(object sender, EventArgs e)
    {
        UncheckOtherToolStripMenuItems((ToolStripMenuItem)sender);
    }

    public void UncheckOtherToolStripMenuItems(ToolStripMenuItem selectedMenuItem)
    {
        selectedMenuItem.Checked = true;

        // Select the other MenuItens from the ParentMenu(OwnerItens) and unchecked this,
        // The current Linq Expression verify if the item is a real ToolStripMenuItem
        // and if the item is a another ToolStripMenuItem to uncheck this.
        foreach (var ltoolStripMenuItem in (from object 
                                                item in selectedMenuItem.Owner.Items 
                                            let ltoolStripMenuItem = item as ToolStripMenuItem 
                                            where ltoolStripMenuItem != null 
                                            where !item.Equals(selectedMenuItem) 
                                            select ltoolStripMenuItem))
            (ltoolStripMenuItem).Checked = false;

        // This line is optional, for show the mainMenu after click
        selectedMenuItem.Owner.Show();
    }

One detail is that you can implement the same method for all click menuItens, for this add same call for method UncheckOtherToolStripMenuItems((ToolStripMenuItem)sender); into the Event click for each ToolstripMenuItem, see this example to the another two ToolstripMenuItens:

    private void subietm2ToolStripMenuItem_Click(object sender, EventArgs e)
    {
        UncheckOtherToolStripMenuItems((ToolStripMenuItem)sender);
    }

    private void subietm3ToolStripMenuItem_Click(object sender, EventArgs e)
    {
        UncheckOtherToolStripMenuItems((ToolStripMenuItem)sender);
    }

OTHER TIPS

I just set all the items in my menu with the event of item_Click so if one is clicked then it will just run the code below. Dont need an event for each button that way.

    private void item_Click(object sender, EventArgs e)
    {
        // Set the current clicked item to item
        ToolStripMenuItem item = sender as ToolStripMenuItem;
        // Loop through all items in the subMenu and uncheck them but do check the clicked item
        foreach (ToolStripMenuItem tempItemp in (ToolStripMenuItem)item.OwnerItem.DropDownItems)
        {
            if (tempItemp == item)
                tempItemp.Checked = true;
            else
                tempItemp.Checked = false;
        }
    }

If you want to add several items to your list during runtime and have them connected in the way above you can run the below code.

    private void subItemsMenus(ToolStripMenuItem parentItem, string[] listItems)
    {
        // Clear tool strip items first
        parentItem.DropDownItems.Clear();
        // Add items that are in the list
        foreach (string subMenuItem in listItems)
        {
            ToolStripMenuItem item = new ToolStripMenuItem();
            //Name that will appear on the menu
            item.Text = subMenuItem; 
            //Put in the Name property whatever necessary to retrieve your data on click event
            item.Name = subMenuItem;
            //On-Click event
            item.Click += new EventHandler(item_Click);
            //Add the submenu to the parent menu
            parentItem.DropDownItems.Add(item);
        }

I have another way which works:

Each item is going to ToolStripMenuItem_CheckStateChanged(object sender, EventArgs e) and every item has its own tag 1, 2, 3, 4, 5. One item is checked on start and has tag = 1.

    int selecteditem = 1;
    bool atwork = false;
    private void dzienToolStripMenuItem_CheckStateChanged(object sender, EventArgs e)
    {
        if (atwork) return;
        else atwork = true;

        selecteditem = Convert.ToInt32(((ToolStripMenuItem)sender).Tag);

        foreach (ToolStripMenuItem it in sometooltipdropdown.DropDownItems)
        {
            if (Convert.ToInt32(it.Tag) != selecteditem)
            {
                it.Checked = false;
            }                
        }

        atwork = false;
    }

The easiest way is add DropDownItemClicked Event and create own method:

private void toolStripDropDownButton1_DropDownItemClicked(object sender, ToolStripItemClickedEventArgs e)
    {
        if (e.ClickedItem != null)
        {
            CheckSelected((ToolStripDropDownButton)sender, e.ClickedItem);
        }
    }

    private void CheckSelected(ToolStripDropDownButton button, ToolStripItem selectedItem)
    {
        foreach (ToolStripMenuItem item in button.DropDownItems)
        {
            item.Checked = (item.Name == selectedItem.Name) ? true : false;
        }
    }

You could get the count by copying to an array and then use extensions.

ToolStripItem[] controls = new ToolStripItem[ToolStrip.DropDownItems.Count];
ToolStrip.DropDownItems.CopyTo(controls,0);
intcheckCount = controls.Count(c => (c as ToolStripMenuItem).Checked);

if (checkCount == 0) // must keep 1 selection
     item.Checked = true;
else if (checkCount > 1)  //uncheck all others
     controls.Cast<ToolStripMenuItem>().Where(c => c.Checked && c.Name != item.Name)
       .ToList().ForEach(s => s.Checked = false);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top