Disable automatic submenu show on hover in ContextMenuStrip - c#

If I have a context menu with sub menu items, is it possible to stop the sub menu from popping out/displaying when I merely hover over the main menu item? And if so, how?

Each ToolStripDropDownItem has a property called DropDown (of type ToolStripDropDown) referring to the drop down which will be shown when the mouse hovers on the item. The ToolStripDropDown has an event called Opening which allows you to cancel the dropping-down easily. Use the following code, all can be set up in your form constructor:
//Suppose the item you want to suppress automatically showing
//the drop down is item1
bool clicked = false;
item1.DropDown.Opening += (s,e) => {
e.Cancel = !clicked;
clicked = false;
};
item1.Click += (s,e) => {
clicked = true;
item1.ShowDropDown();
};
//The code above disables the automatic dropping-down
//and shows the drop down by clicking on the item1.

Related

Show property editor by click on property text box in PropertyGrid

I am creating a touch application on a no-keyboard pc, where I use a PropertyGrid to manage classes to store / save the app configuration.
I need to edit the propertyline's rows with a custom keyboard that I created (not the system's) setting the class as UITypeEditor
Now the custom keyboard is showed when right button is clicked.
Is it possible to show when on the row start edit (like textbox Enter event),
or when the row is selected ?
The editor control which you see in PropertyGrid is a GridViewEdit control which is a child of PropertyGridView which is a child of the PropertyGrid.
You can find the edit control and assign an event handler to its Enter event. In this event, you can find the SelectedGridItem and then call its EditPropertyValue method which is responsible to show the UITypeEditor.
private void propertyGrid1_SelectedObjectsChanged(object sender, EventArgs e)
{
var grid = propertyGrid1.Controls.Cast<Control>()
.Where(x => x.GetType().Name == "PropertyGridView").FirstOrDefault();
var edit = grid.Controls.Cast<Control>()
.Where(x => x.GetType().Name == "GridViewEdit").FirstOrDefault();
edit.Enter -= edit_Enter;
edit.Enter += edit_Enter;
}
private void edit_Enter(object sender, EventArgs e)
{
var item = this.propertyGrid1.SelectedGridItem;
if (item.GetType().Name == "PropertyDescriptorGridEntry")
{
var method = item.GetType().GetMethod("EditPropertyValue",
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Instance);
var grid = propertyGrid1.Controls.Cast<Control>()
.Where(x => x.GetType().Name == "PropertyGridView").FirstOrDefault();
method.Invoke(item, new object[] { grid });
}
}
Note: For modal editors the Enter event is annoying and repeats over and over again. To avoid this you can use Click event of the control.
Also as another option you can rely on SelectedGridItemChanged event of PropertyGrid and check if e.NewSelection.GetType().Name == "PropertyDescriptorGridEntry" then call EditPropertyValue of the selected grid item using reflection.

How do I use the DevExpress DropDownButton c#?

I am trying to create a dropdown so that users can see the names of accounts. How do i do that using DevExpress DropDown Button?
You should associate the drop-down button with a popup control/context menu. To accomplish this task use the DropDownControl property.
DXPopupMenu menu = new DXPopupMenu();
menu.Items.Add(new DXMenuItem("Admin"));
menu.Items.Add(new DXMenuItem("Guest"));
// ... add more items
dropDownButton1.DropDownControl = menu;
// subscribe item.Click event
foreach(DXMenuItem item in menu.Items)
item.Click += item_Click;
// setup initial selection
dropDownButton1.Text = menu.Items[0].Caption;
//...
void item_Click(object sender, EventArgs e) {
// synchronize selection
dropDownButton1.Text = ((DXMenuItem)sender).Caption;
// ... do something specific
}
The following objects can be used as popup controls:
PopupMenu - represents a popup menu managed by a BarManager or RibbonControl component.
PopupControlContainer - represents a container for other controls. This control is also managed by a BarManager component.
DXPopupMenu - represents a popup menu.

right-click doesn't work with toolstripmenuitem

I have some code:
_Item.MouseDown += new MouseEventHandler(delegate(Object o, MouseEventArgs a)
{
SrcRoot = BuilderParametresPath[_index].pngPath;
DstRoot = BuilderParametresPath[_index].scenesPath;
TextsXmlFileName = BuilderParametresPath[_index].textsPath;
NavigationSystemPath = BuilderParametresPath[_index].hintPath;
LevelsXmlFileName = BuilderParametresPath[_index].LevelsFilePath;
if (a.Button == MouseButtons.Right)
{
ContextMenuStrip docMenu = new ContextMenuStrip();
ToolStripMenuItem deleteLabel = new ToolStripMenuItem();
deleteLabel.Text = "Удалить";
docMenu.Items.AddRange(new ToolStripMenuItem[] { deleteLabel });
ocMenu.Show(MousePosition);
}
});
But it does not work, because pressing the right button does not work out. What can be done?
Add a contextMenuStrip control to the form.
Now enter some menu items in the menu strip.
Click the target control which may be button/textbox/form and go to properties and in the properties select ContextMenuStrip and set the required contextMenuStrip control.
Then the context menu strip for the target control will appear when you right click to the targetead control.

How to Leave ToolStripMenu Open After Clicking an Item

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

C# - Passing focus to a tabcontrol/page and not being able to mousewheel scroll

I have a combobox with four items that correspond to tabs in a tabcontrol. When the user selects an item from the combobox (by left clicking and left clicking again to select an item) the corresponding tabpage in the tabcontrol is selected. The tabpage is set to autoscroll but when the tabpage is selected in this way mousewheel scrolling does not work. (If I click a control inside that tabpage manually I can then mousewheel scroll..)
If the user mousewheels to select an item from the same combobox (and successfully passes control to the corresponding tabpage) mousewheel scrolling works fine on that tabpage and I cant figure out why.
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
switch (comboBox1.SelectedIndex)
{
case 0:
tabControl1.SelectedTab = tabPage3;
tabPage3.Focus();
break;
}
...
}
I can't get a repro of this problem. Something that might help is to set the focus to the first control of the page instead, just like what happens when you fix the problem by clicking a control. And to do so later, after the combobox event is completed. Use this:
private void setFocusToPage(TabPage page) {
var ctl = page.Controls.Count > 0 ? page.Controls[0] : page;
this.BeginInvoke((MethodInvoker)delegate { ctl.Focus(); });
}
Call setFocusToPage instead of the Focus() method in your SelectedIndexChanged event handler.

Categories