Reputation: 6038
I'm creating a ToolStripMenu
shown below that is supposed to allow the user to interact with the items "XML" and "Non XML" as though they are regular check boxes on a form. However, when one item is checked/unchecked the menu closes. How can I allow an item to be checked/unchecked without closing the menu? Or is there a different standard method of achieving the same behavior?
So what I want is to be able to click on "Non XML", show a check box and leave the menu open. The idea is that the last menu item will be "Done" and when it's clicked the "G2S" sub items will remain open but the "Display" sub items ( XML, Non XML ) will close.
Any ideas?
Note: I am aware that this is likely not the best user interface design. I'd like to know however how this could be accomplished just to gain some technical knowledge about handling menus.
Upvotes: 5
Views: 9500
Reputation:
If someone is still interested, here is a vb solution:
1) For the parent tool strip menu item, add the following handler in the form's constructor:
AddHandler ParentTSMI.DropDown.Closing, AddressOf onDropDownClosing
2) The handler:
Private Sub onDropDownClosing(sender As Object, e As ToolStripDropDownClosingEventArgs)
If e.CloseReason = ToolStripDropDownCloseReason.ItemClicked Then
e.Cancel = True
End If
End Sub
That's it all.
Don't forget to remove the handler (RemoveHandler) when you close the form.
Upvotes: 1
Reputation: 31
Here's a useful extension that requires user to click outside of menu item + dropdowns to close.
public static void KeepOpenOnDropdownCheck (this ToolStripMenuItem ctl)
{
foreach (var item in ctl.DropDownItems.OfType<ToolStripMenuItem>())
{
item.MouseEnter += (o, e) => ctl.DropDown.AutoClose = false;
item.MouseLeave += (o, e) => ctl.DropDown.AutoClose = true;
}
}
Upvotes: 3
Reputation: 857
I used a combination of Neolisk's and Chimera's answers to allow deletion of multiple leaf items from a treeview. My solution is below
Note: the following Items created at design time are used: TreePromotions (TreeView) menuVendorSection (Context Menu Strip) removeMultipleItemsToolStripMenuItem (DropDown of menuVendorSection)
private void removeMultipleItemsToolStripMenuItem_MouseHover(object sender, EventArgs e)
{
removeMultipleItemsToolStripMenuItem.DropDownItems.Clear();
ToolStripMenuItem detailMenuItem;
TreeNode vendorSectionNode = treePromotions.SelectedNode;
for (int vsn = 0; vsn < vendorSectionNode.Nodes.Count; vsn++)
{
//add checkbox item
detailMenuItem = new ToolStripMenuItem(vendorSectionNode.Nodes[vsn].Text);
detailMenuItem.Tag = vendorSectionNode.Nodes[vsn].Tag;
detailMenuItem.CheckOnClick = true;
removeMultipleItemsToolStripMenuItem.DropDownItems.Add(detailMenuItem);
}
//add action buttons
Button buttonDeleteMultiple = new Button();
buttonDeleteMultiple.Text = "Remove Checked Items";
ToolStripControlHost buttonHost = new ToolStripControlHost(buttonDeleteMultiple);
buttonDeleteMultiple.Click += new EventHandler(buttonDeleteMultiple_Click);
removeMultipleItemsToolStripMenuItem.DropDownItems.Add(buttonHost);
Button buttonCancelMultipleDelete = new Button();
buttonCancelMultipleDelete.Text = "CANCEL";
buttonHost = new ToolStripControlHost(buttonCancelMultipleDelete);
buttonCancelMultipleDelete.Click += new EventHandler(buttonCancelMultipleDelete_Click);
removeMultipleItemsToolStripMenuItem.DropDownItems.Add(buttonHost);
removeMultipleItemsToolStripMenuItem.DropDown.AutoClose = false;
menuVendorSection.AutoClose = false;
}
private void buttonDeleteMultiple_Click(object sender, EventArgs e)
{
//delete items
for (int dmi = 0; dmi < removeAllItemsToolStripMenuItem.DropDownItems.Count - 2; dmi++) //do not include buttons
{
((Detail)removeAllItemsToolStripMenuItem.DropDownItems[dmi].Tag).Delete(); //deletes item from database
}
//rebuild leaf
treePromotions.SelectedNode.Nodes.Clear();
addItemNodes(treePromotions.SelectedNode); //builds leaf nodes from database
//close menus
removeMultipleItemsToolStripMenuItem.DropDown.Close();
menuVendorSection.AutoClose = true;
menuVendorSection.Close();
}
private void buttonCancelMultipleDelete_Click(object sender, EventArgs e)
{
//just close menus
removeMultipleItemsToolStripMenuItem.DropDown.Close();
menuVendorSection.AutoClose = true;
menuVendorSection.Close();
}
Upvotes: 1
Reputation: 17
The original solution will work with the use of mouse events.
On mouse enter event:
parent.dropdown.autoclose = false;
on mouse leave event:
parent.dropdown.autoclose = true;
The only catch is if the user access the menu items by other means than a mouse.
Upvotes: 0
Reputation: 26454
Interesting concept is described in this thread on Stackoverflow:
Here is the essence of the accepted answer:
ParentMenu.DropDown.AutoClose = false;
It does exactly what you are asking for - prevent menu from closing when subitem is clicked.
Upvotes: 5
Reputation: 6038
Posted in case somebody finds it helpful.
Instead of trying to do exactly what I had originally intended, I've come up with the following:
1- Use a ContextMenuStrip
2- When the user clicks on the ToolStripMenu
item I display the ContextMenuStrip
at a location near the menu item as shown below: ( note the positioning still needs adjusting )
To get this working I build the ContextMenuStrip
in code at run-time so that the items in the ContextMenuStrip
can be build dynamically based on the situation.
Code snippets:
Show the ContextMenuStrip
when the menu item is clicked:
private void filterToolStripMenuItem_Click(object sender, EventArgs e)
{
contextMenuStrip1.Show(this, 180, 20);
}
Build the ContextMenuStrip
:
if (protInfo.Name == "QCOM" )
{
BroadCast = new CheckBox();
BroadCast.Text = "Date/Time Broadcast";
BroadCast.Checked = FlagSet(CurrentFilter, (Byte)Filter.DateTimeBC);
ToolStripControlHost Ch1 = new ToolStripControlHost(BroadCast);
GenPoll = new CheckBox();
GenPoll.Text = "Status Poll";
GenPoll.Checked = FlagSet(CurrentFilter, (Byte)Filter.GenStatusPoll);
ToolStripControlHost Ch2 = new ToolStripControlHost(GenPoll);
GenPollResp = new CheckBox();
GenPollResp.Text = "Status Poll Response";
GenPollResp.Checked = FlagSet(CurrentFilter, (Byte)Filter.GenStatusResponse);
ToolStripControlHost Ch3 = new ToolStripControlHost(GenPollResp);
Button btnDone = new Button();
btnDone.Text = "Done";
ToolStripControlHost Ch4 = new ToolStripControlHost(btnDone);
btnDone.Click += new EventHandler(btnDone_Click);
contextMenuStrip1.Items.Clear();
contextMenuStrip1.Items.Add(Ch1);
contextMenuStrip1.Items.Add(Ch2);
contextMenuStrip1.Items.Add(Ch3);
contextMenuStrip1.Items.Add(Ch4);
contextMenuStrip1.Enabled = true;
filterToolStripMenuItem.Enabled = true;
}
else
{
filterToolStripMenuItem.Enabled = false;
}
This may not be the best user interface design, but it seems to work.
Upvotes: 2