Finding and Creating Sub Menus Dynamically - c#

I have a ToolStripMenuItem I need to check if it has a sub menu with a particular name, if it exists, add a new menu item to that sub menu, and if not, create the sub menu and add the item to the new sub menu.
ToolStripItemCollection menu = tsmi1.DropDownItems;
for(int i = 0; i < menu.Count; i++) {
if(item.Category.Equals(menu[i].Text)) {
menu[i]. //need to add new menu item here....
}
}
It may just be that I don't understand how the menu system actually works, but it appears I can't add an item to my menu object.

Is your sub-menu a ToolStripDropDownItem?
The objects in TooLStripItemCollection are all of type ToolStripItem. You may need to cast the item you find to the derived class, ToolStripDropDownItem.
That will give you access to its DropDownItems collection, which is another ToolStripItemCollection and has Add, AddRange, and Insert methods.
I haven't worked with ToolStripDropDownItem myself, but that's the path I'd start on.
Edit by bwoogie:
Final code:
ToolStripMenuItem tsmi = new ToolStripMenuItem();
tsmi.Text = item.Name;
tsmi.Click += node_Click;
ToolStripItemCollection nodeMenu = nodesToolStripMenuItem.DropDownItems;
for (int i = 0; i < nodeMenu.Count; i++) {
if (item.Category.Equals(nodeMenu[i].Text)) {
((ToolStripMenuItem)nodeMenu[i]).DropDownItems.Add(tsmi);
} else {
ToolStripItem newtsi = nodeMenu.Add(item.Category);
((ToolStripMenuItem)newtsi).DropDownItems.Add(tsmi);
}
}

Related

C# ComboBox Items not displaying

I think it is a small problem but I can't find my mistake.
I create a Form called Inventurbeleg which contains a ComboBox called cbProduktBox.
With a Controller-Class I create an Object of the Form. Now I want to add Items with the create-Methode.
public static void buttonCreate()
{
inventurbeleg = new Inventurbeleg();
create();
inventurbeleg.Show();
}
My ComboBox gets Items from an array:
public static void create()
{
inventurbeleg.cbProduktBox = new ComboBox();
for (int j = 0; j < Program.arrayMatNr.GetLength(0); j++)
{
String item = Program.arrayMatNr[j, 1];
inventurbeleg.cbProduktBox.Items.Add(item);
}
}
This works correctly, cbProduktBox contains all Items. My Problem is, that the Items arn't shown at my Form. There is an empty comboBox.
You can't do it like that, take a look at this line:
inventurbeleg.cbProduktBox = new ComboBox();
You're creating a new combobox, and when the form loads, the cbProduktBox will initialize again and the changes will be gone
Maybe you can move the create method inside the new form, so when the form loads, call the create method.

Adding menu items during runtime in C#

I'm still working on getting a menu to display all of the input devices on a computer- pardon my third question in something that is probably very simple.
Here's the code:
List<MenuItem> inputDevice = new List<MenuItem>();
MenuItem myMenuItemInputDevices = new MenuItem("&Input Devices");
sgFileMenu.MenuItems.Add(myMenuItemInputDevice);
for (int i = 0; i < DeviceCount; i++)
{
inputDeviceMenu.Add(new MenuItem(inputName[i]));
myMenuItemInputDevices.MenuItems.Add(inputDeviceMenu[i]);
myMenuItemInputDevices.Click += new System.EventHandler(this.myMenuItemInputDeviceClick);
}
This seems to work just fine, the menu items are added, everything is good, but clicks on the dropdown list are not working. I've done other work with menus, and clicks in other code are working correctly. I tried putting
myMenuItemInputDevices.Click += new System.EventHandler(this.myMenuItemInputDeviceClick);
outside of the {}, just in case that was the right way to do it, but that didn't help.
What am I missing?
You want this
List<MenuItem> inputDevice = new List<MenuItem>();
MenuItem myMenuItemInputDevices = new MenuItem("&Input Devices");
sgFileMenu.MenuItems.Add(myMenuItemInputDevice);
for (int i = 0; i < DeviceCount; i++)
{
inputDeviceMenu.Add(new MenuItem(inputName[i]));
inputDeviceMenu[i].Click += new System.EventHandler(this.myMenuItemInputDeviceClick);
myMenuItemInputDevices.MenuItems.Add(inputDeviceMenu[i]);
myMenuItemInputDevices.Click += new System.EventHandler(this.myMenuItemInputDeviceClick);
}
EDIT: It is pretty obvious that the Menu Items that you are trying to add does not have any Click event method hooked up.
inputDeviceMenu.Add(new MenuItem(inputName[i]));
You are just adding them.

How to copy MenuItem from one ContextMenu to another ContextMenu

How do I copy a MenuItem I created in one ContextMenu and copy it so that I can use it in a second ContextMenu?
I tried to copy it directly and removing it, but I get Element already has a logical parent. It must be detached from the old parent before it is attached to a new one.
foreach(MenuItem mi in menuOptions.Items) {
entityRightClick.Items.Add(mi);
menuOptions.Items.Remove(mi);
}
I tried grabbing the MenuItem using the ItemContainerGenerator, it gave me a blank MenuItem (Debugger says that it is null)
for(int i = 0; i < menuOptions.Items.Count; i++) {
MenuItem temp = new MenuItem();
temp = menuOptions.ItemContainerGenerator.ContainerFromIndex(i) as MenuItem;
entityRightClick.Items.Add(temp);
}
Based on your error message, I'd expect this to work (though I haven't tested it):
foreach(MenuItem mi in menuOptions.Items)
{
menuOptions.Items.Remove(mi);
entityRightClick.Items.Add(mi);
}

ToolStripMenuItem for multiple ContextMenuStrip

I have a form which contains tab panel with many tap pages. Each of them has its own context menu (display on right-click). But If I add a ToolStripMenuItem to multiple ContextMenuStrips only last menu strip really has this menu item.
Simple code example is:
ToolStripMenuItem tim_refresh = new ToolStripMenuItem("Refresh", null, (o, e) =>
{
MessageBox.Show("Refresh");
});
ContextMenuStrip cms1 = new ContextMenuStrip();
cms1.Items.Add(tim_refresh);
ContextMenuStrip cms2 = new ContextMenuStrip();
cms2.Items.Add(tim_refresh);
this.tblDataManagerObjects.ContextMenuStrip = cms1;
this.tblDataSourceTypes.ContextMenuStrip = cms2;
If one shows this menus one by one, first will be empty...How can I achieve what I want?
Thi is because visual can not be child of multiple diferent visuals in the same time. In your case tim_refresh is a child of cms1 and cms2 at the same time.
You need to create two completely separate instances of ToolStripMenuItem.
EDIT:
You can extract visual creation in factor method to simplify multiple objects instantiation:
private ToolStripMenuItem CreateToolStripMenuItem(string name)
{
return new ToolStripMenuItem(name, null, (o, e) =>
{
MessageBox.Show(name);
});
}
// then just call it once per each menu strip
ContextMenuStrip cms1 = new ContextMenuStrip();
cms1.Items.Add(CreateToolStripMenuItem("Refresh"));
ContextMenuStrip cms2 = new ContextMenuStrip();
cms2.Items.Add(CreateToolStripMenuItem("Refresh"));
one context menu is displayed once at a time; you probably don't need many clones everywhere, but you may want to move one single instance of your menu items to the menu menu strip at the moment menu strip is opening;
I'm moving here the named (grand) parent's items to the child (currently opening) menu when the local copy is empty, and all the next ctx openings I just AddRange, which moves the "located" three menu items from the previously opened ctxMenuStrip to the currently-opening-one:
// http://stackoverflow.com/questions/8307959/toolstripmenuitem-for-multiple-contextmenustrip?rq=1
// http://stackoverflow.com/questions/6275120/toolstripmenuitem-added-to-several-places?rq=1
// WILL_ADD_PARENT_MENU_ITEMS_IN_Opening first time opened we locate common menu items from GrandParent, then we move them to the current slider; cool?
private static ToolStripItem[] separatorLoadSave = null;
private void contextMenuStrip1_Opening(object sender, CancelEventArgs e) {
if (separatorLoadSave == null) {
separatorLoadSave = new ToolStripItem[3];
Control slidersAutoGrow = base.Parent;
if (base.Parent.Name != "SlidersAutoGrow") return;
Control slidersForm = slidersAutoGrow.Parent;
if (slidersForm.Name != "SlidersForm") return;
ToolStripItem[] separator = slidersForm.ContextMenuStrip.Items.Find("toolStripSeparator1", false);
if (separator.Length > 0) separatorLoadSave[0] = separator[0];
ToolStripItem[] load = slidersForm.ContextMenuStrip.Items.Find("mniParameterSetLoad", false);
if (load.Length > 0) separatorLoadSave[1] = load[0];
ToolStripItem[] save = slidersForm.ContextMenuStrip.Items.Find("mniParameterSetSave", false);
if (save.Length > 0) separatorLoadSave[2] = save[0];
}
this.contextMenuStrip1.SuspendLayout();
this.contextMenuStrip1.Items.AddRange(separatorLoadSave);
this.contextMenuStrip1.ResumeLayout();
}

about toolStripDropDownButton

I have a form. I've added the strip down button using drag and drop in the form. How can I (in the program) create and fill the toolStripMenu Item? My menu could contain different element...with different names.
If you want to add items programmatically to a ToolStripDropDownButton just do:
var item1 = new ToolStripButton("my button");
toolStripDropDownButton1.DropDownItems.Add(item1);
var item2 = new ToolStripComboBox("my combo");
toolStripDropDownButton1.DropDownItems.Add(item2);
// etc ...
Instead, if you need to add other ToolStripDropDownButton or other elements directly to you menu (ToolStrip), just do:
var item1 = new ToolStripDropDownButton("my dropdown button");
toolStrip1.Items.Add(item1);
var item2 = new ToolStripProgressBar("my progress bar");
toolStrip1.Items.Add(item2);
// etc ...
EDIT:
You must do it after InitializeComponent() otherwise you won't be able to access to design-time added components, e.g.:
InitializeComponent();
// we're after InitializeComponent...
// let's add 10 buttons under "toolStripDropDownButton1" ...
for (int i = 0; i < 10; i++)
{
var item = new ToolStripButton("Button_"+i);
toolStripDropDownButton1.DropDownItems.Add(item);
}
For the DropDown property you need a ContextMenuStrip. The easiest way to find out how to fill it up is to drag&drop one from the toolbox onto your form, fill it up, select it in the DropDown property and afterwards take a look into the Designer.cs file to see how all the stuff is glued together.
The drawback of using the DropDownItems property is that you can't alter some properties like ShowImageMargin.

Categories