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 ответ
Для решения проблемы вы можете выполнить следующие действия:
Вы должны определить, какие пункты меню должны оставаться открытыми даже после нажатия на них. Я буду использовать "keepopen" в качестве значения
Tag
свойство для тех элементов, которые должны оставаться открытыми после нажатия.Для пункта меню, который содержит эти пункты, вам нужно получить
DropDown
собственность и и обрабатывать егоItemClicked
событие и вItemClicked
событие, вы должны проверить, является ли элемент, который нажал"keepopen"
предметы, а затем установитьDropDown.AutoClose
элемента меню контейнера дляfalse
, Для других предметов установите его наtrue
, Это не позволит закрыть те"keepopen"
элемент при нажатии, пока другие объекты закрываются при нажатии.Вы должны справиться
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;
};
});
}