MenuItem AutoClose = false для динамически генерируемого меню панели инструментов

Итак, следуя этому вопросу, я пытался найти способ остановить закрытие выпадающего меню при нажатии на элемент.

В связанном вопросе один такой ответ предложил мне установить AutoClose свойство ложно. Я так и сделал, и это добилось того, что я просил. Однако то, как я это реализовал, означает, что раскрывающееся меню принудительно открывается.

Код формы:

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 быть установленным в истину. Однако, поскольку 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 ответ

Для решения проблемы вы можете выполнить следующие действия:

  1. Вы должны определить, какие пункты меню должны оставаться открытыми даже после нажатия на них. Я буду использовать "keepopen" в качестве значения Tag свойство для тех элементов, которые должны оставаться открытыми после нажатия.

  2. Для пункта меню, который содержит эти пункты, вам нужно получить DropDown собственность и и обрабатывать его ItemClicked событие и в ItemClicked событие, вы должны проверить, является ли элемент, который нажал "keepopen" предметы, а затем установить DropDown.AutoClose элемента меню контейнера для false, Для других предметов установите его на true, Это не позволит закрыть те "keepopen" элемент при нажатии, пока другие объекты закрываются при нажатии.

  3. Вы должны справиться CheckedChanged событие тех "keepopen" предметы и набор DropDown.AutoClose в true, При использовании Click В обработчике событий мы запретили закрытие элементов, здесь мы снова включаем закрытие, поэтому, если пользователь щелкнет за пределами меню, оно закроется.

Тогда это будет результат, посмотрите на щелчки мыши:

пример

В качестве примера создайте пустую форму и обработайте ее Load событие и используйте следующий код. Когда вы нажимаете на SubMenu1, SubMenu2 или же SubMenu3, они будут просто проверены или сняты без закрытия меню. Но вы нажимаете за пределами меню или на 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;
            };
        });
}
Другие вопросы по тегам