动态生成的工具栏菜单上的MenuItem AutoClose = false

时间:2017-10-31 00:00:37

标签: c# .net winforms toolstripdropdown

所以,在this question之后,我一直试图处理一种方法,当我点击某个项目时停止下拉菜单关闭。

在链接的问题中,有一个这样的答案表明我将AutoClose属性设置为false。我这样做了,这确实实现了我的要求。但是,我实现它的方式意味着下拉菜单被强制打开。

表单代码:

public void ToolStripMenuItem_Click(object sender, EventArgs e)
{
    ToolStripMenuItem item = sender as ToolStripMenuItem;
    if (item != null)
        item.Checked = !item.Checked;

    item.DropDown.AutoClose = false;
}

我知道为什么会这样 - 实现意味着无法将AutoClose设置为true。但是,由于menuItems是在不同的类中动态生成的,因此我没有任何要引用的事件或对象。

此代码从主窗体复制菜单结构,并将其复制以在“配置文件视图”中重新创建它(以设置用户可以/不能看到的内容)。

控制器代码:

private void PopulateProfileView(User_AccessProfilesView view, Menu_View mainMenu)
{
    // Disabled Items are not able to be set, becasue they are either always visible for every user,
    // or only visible to specific users (Administrator)
    List<string> disabledMenuItems = new List<string>();
    List<string> disabledSubMenuItems = new List<string>();

    bool error = false;          
    bool subError = false;
    _groupDictionary = new Dictionary<string, List<string>>();

    // Populate the disallowed Menu Items from the Main Menu,
    // and then add the items specific to the Profile View
    disabledMenuItems.Add("File");
    disabledMenuItems.Add("Administrator");
    disabledMenuItems.Add("Help");
    disabledMenuItems.Add("Te&rminations");
    disabledMenuItems.AddRange(mainMenu.disallowedMenuItems);

    // Populate the disallowed Sub Menu Items from the Main Menu,
    // and then add the items specific to the Profile View
    disabledSubMenuItems.Add("View All");
    disabledSubMenuItems.AddRange(mainMenu.disallowedSubItems);

    foreach (ToolStripMenuItem item in mainMenu.mainMenuStrip.Items)
    {
        ToolStripMenuItem menuItem = new ToolStripMenuItem(item.Text);

        if (error == false)
        {
            // Add to the menu bar
            view.menuStrip.Items.Add(menuItem);
            menuItem.Click += new EventHandler(view.ToolStripMenuItem_Click);

            foreach (ToolStripItem dropItem in item.DropDownItems)
            {
                if (dropItem is ToolStripMenuItem)
                {
                    ToolStripMenuItem menuDropItem = new ToolStripMenuItem(dropItem.Text);

                    // Same concerns as above with regards to doing a substring check
                    // to decide if menu items should be excluded or not.
                    foreach (string s1 in disabledSubMenuItems)
                    {
                        if (!menuDropItem.Text.Contains(s1))
                        {
                            subError = false;
                        }
                        else
                        {
                            subError = true;
                            break;
                        }
                    }

                    if (!subError)
                    {
                        menuItem.DropDownItems.Add(menuDropItem);
                        menuDropItem.Click += new EventHandler(view.ToolStripMenuItem_Click);
                    }
                }
                else if (dropItem is ToolStripSeparator)
                { menuItem.DropDownItems.Add(new ToolStripSeparator()); }
            }

如何正确实现AutoClose属性,以便在单击菜单项时,菜单不会关闭,但如果单击菜单标题,或将鼠标从菜单中移开,或者选择另一个菜单(通过单击或鼠标悬停),菜单会关闭吗?

道歉,如果这是一个简单的问题 - 我已经离开游戏大约一年了,不得不重新回到这一点,并且在一切正常后我会遇到一些问题。

1 个答案:

答案 0 :(得分:2)

要解决此问题,您可以按照以下步骤操作:

  1. 您应确定哪些菜单项在点击后仍应保持打开状态。我将使用“keepopen”作为Tag属性的值,用于那些在点击后应保持打开的项目。

  2. 对于包含这些项目的菜单项,您需要获取DropDown属性并处理其ItemClicked事件,并且在ItemClicked事件中,您应该检查单击的项是其中一个"keepopen"项,然后将容器菜单项的DropDown.AutoClose设置为false。对于其他项目,请将其设置为true。它会阻止在点击时关闭这些"keepopen"项目,同时通过点击关闭其他项目。

  3. 您应该处理这些CheckedChanged项的"keepopen"个事件,并将DropDown.AutoClose设置为true。在使用Click事件处理程序时,我们阻止了项目关闭,这里我们再次启用关闭,因此如果用户单击菜单外部,它将关闭。

  4. 然后这就是结果,看鼠标点击:

    enter image description here

    示例

    例如,创建一个空表单并处理其Load事件并使用以下代码。当您点击SubMenu1SubMenu2SubMenu3时,只需选中或取消选中它们,而无需关闭菜单。但是你点击菜单外面或SubMenu4,它会关闭菜单。

    const string keepopen = "keepopen";
    private void Form1_Load(object sender, EventArgs e)
    {
        var menuStrip = new MenuStrip() { Dock = DockStyle.Top };
        this.Controls.Add(menuStrip);
        var menu1 = (ToolStripMenuItem)menuStrip.Items.Add("Menu1");
        menu1.DropDownItems.Add(new ToolStripMenuItem("Submenu1")
        { Tag = keepopen, CheckOnClick = true });
        menu1.DropDownItems.Add(new ToolStripMenuItem("Submenu2")
        { Tag = keepopen, CheckOnClick = true });
        menu1.DropDownItems.Add(new ToolStripMenuItem("Submenu3")
        { Tag = keepopen, CheckOnClick = true });
        menu1.DropDownItems.Add("-");
        menu1.DropDownItems.Add(new ToolStripMenuItem("Submenu4"));
        menu1.DropDown.ItemClicked += (obj, args) =>
        {
            if (args.ClickedItem.Tag == keepopen)
                menu1.DropDown.AutoClose = false;
            else
                menu1.DropDown.AutoClose = true;
        };
        menu1.DropDownItems.OfType<ToolStripMenuItem>()
            .Where(x => x.Tag == keepopen)
            .ToList().ForEach(x =>
            {
                x.CheckedChanged += (obj, args) =>
                {
                    menu1.DropDown.AutoClose = true;
                };
            });
    }