只选中一个ToolStrip菜单项

10
我有一个包含多个ToolStripDropDownButton的ToolStrip,每个ToolStripDropDownButton都有一组DropDownItems。当用户点击DropDownItem时,会显示选中标记。
默认情况下,多个项可以被点击,因此会出现多个选中标记。
我想做的是,当用户点击一个DropDownItem时,其他已经被选中的项应该取消选中。换句话说,在DropDown列表中应始终只有一个选中项。
我已经尝试过一段时间,但我真的无法弄清楚如何让当前选中的项保持不变,同时取消其他项的选中状态。
以下是我目前的代码。
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;
                }
            }
        }

如果有人能为此提供一些见解或告诉我一个简单的方法,我将不胜感激。
谢谢。

http://msdn.microsoft.com/en-us/library/ms404318.aspx - Cody Gray
5个回答

16

太容易了...

按照下面描述的方法实现:

    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();
    }

一个细节是您可以针对所有点击菜单项实现相同的方法,只需将UncheckOtherToolStripMenuItems((ToolStripMenuItem)sender);的相同调用添加到每个ToolstripMenuItem的click事件中即可。请参考此示例来处理另外两个ToolstripMenuItens:

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

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

感谢您的回复,但它只适用于DropDownList中的第一个ToolStripMenuItem。 - Isuru
我已编辑答案。如果满足您的需求,请评价该问题。 - Julio Borges
谢谢。它可以工作。但是我遇到了一个小问题。当下拉列表中有ToolStripSeparator时,我会收到InvalidCastException错误。_无法将类型为'System.Windows.Forms.ToolStripSeparator'的对象强制转换为类型'System.Windows.Forms.ToolStripMenuItem'._你有什么建议来解决这个问题吗?再次感谢。 :) - Isuru
现在它运行得非常好!非常感谢! :) 我需要尽快学习这个LINQ东西。 - Isuru
1
@isuru,Linq很酷!!!看看这个学习的链接: http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b http://www.linqpad.net/ - Julio Borges
显示剩余2条评论

3

我刚刚将菜单中的所有项目都设置为item_Click事件,因此如果单击其中一个,则只会运行下面的代码。这样就不需要为每个按钮设置一个事件。

    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;
        }
    }

如果您想在运行时添加多个项目并按上述方式将它们连接起来,可以运行以下代码。
    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);
        }

1
最简单的方法是添加 DropDownItemClicked 事件并创建自己的方法:
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;
        }
    }

1
我有另一种方法可以解决:
每个项目都会触发 ToolStripMenuItem_CheckStateChanged(object sender, EventArgs e),并且每个项目都有自己的标签 1, 2, 3, 4, 5。 在启动时检查一个项目,并具有 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;
    }

0

您可以通过将数据复制到数组中,然后使用扩展方法来获取计数。

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);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接