Dynamically adding ToolStripMenuItems to a MenuStrip (C#/ Winforms)
Asked Answered
S

5

20

I have my solution implemented (basic solution) and I'm happy.

Problem is when I add new items to a ToolStripItemCollection using the 'Add' method, I get a few overloads ... the meaningful one being a string parameter, an image parameter and an EventHandler parameter.

Because my drop down list is going to be serving as a dynamic history at RunTime, means it going to be empty at compile time. This means I can't add an event handler through the standard route of using the designer surface (On click). I am forced to use the overload described above.

I image is of no use to me but adding the event handler dynamically is what I am interested in and need help with.

URL: http://msdn.microsoft.com/en-us/library/bxdt0s8t.aspx

There is no other overload to help me, so I have to use an Image ... anyone got any ideas to get around this and show me how to fully satisfy this overloaded version of the add method.

TIA.

UPDATE: I re did this again in a current project but using more slicker code but the principle is the same, add event handlers dynamically at run time. I will update this with some sample code when I get home.

Ss answered 18/11, 2009 at 17:12 Comment(0)
B
40

The way I do it is to create an array of ToolStripMenuItems and populate that array with the items I'm adding. I create one method to handle the click events and have it check something unique about each item I create at run-time. You might try using the Name or Tag properties of each ToolStripMenuItem. Then use AddRange on the spot in the menu you're adding to. So your code might look something like this:

private void BuildMenuItems()
{
    ToolStripMenuItem[] items = new ToolStripMenuItem[2]; // You would obviously calculate this value at runtime
    for (int i = 0; i < items.Length; i++)
    {
        items[i] = new ToolStripMenuItem();
        items[i].Name = "dynamicItem" + i.ToString();
        items[i].Tag = "specialDataHere";
        items[i].Text = "Visible Menu Text Here";    
        items[i].Click += new EventHandler(MenuItemClickHandler);
    }

    myMenu.DropDownItems.AddRange(items);
}

private void MenuItemClickHandler(object sender, EventArgs e)
{
    ToolStripMenuItem clickedItem = (ToolStripMenuItem)sender;
    // Take some action based on the data in clickedItem
}
Betweenwhiles answered 18/11, 2009 at 17:19 Comment(5)
thanks for the replying ... this looks promsing alhough I would like to try out the Add methods overload first that seems like the one for the job if someone on here can show me how .... = ) I remain optimistic ....Ss
The Add method works the same way. Don't create an array and then make the for loop work on a single item: ToolStripMenuItem item = new ToolStripMenuItem(); and then at the end of the for loop call: myMenu.Items.Add(item);Betweenwhiles
Ty I took some clues from your reply and got it working beautifully. Right now the last thing I need to do for my app before I move onto the next big chapter is come up with a method that reshuffles my history menu, to allow a new item to be added and the rest are moved up. This should be simple enuff as I have tested out it out and everything seems brill so far.Ss
hmm this will leak if BuildMenuItems is called more than onceMarilee
@jk not only will it leak if called more than once - the event will be fired more than once. At the beginning of the code unsubscribe items[i].Click -= new EventHandler(MenuItemClickHandler); myMenu.DropDownItems.Remove(items[i]); of course the other needed error handling checks should be there as well but this is the jist.Allies
A
1

What is wrong with:

ToolStripItem item = toolStripItems.Add("MyItem");
item.Click += new EventHandler(....);

Am I missing something?

Anschauung answered 19/11, 2009 at 20:41 Comment(2)
Dunno mate, am relatively inexperienced but thanks to JasonH I was able to use the following. Nothing wrong with that really, I was more keen on using one of the overloads as pose to solutions mentioned above......................................................................... historyToolStripMenuItem.DropDownItems.Add(treeDrives.SelectedNode.FullPath, null, new EventHandler(MenuItemClickHandler)); This is exactly what I was after ... and works beautifullySs
As you can see I am using the FullPath property to give the item a meaningful name as it relates to the file that has been launched, null because am not using any images and the event handler at the end. This is the overload that I was struggling with ... seems simple now = ). Incase you are wondering this is going to append recently executed files to the history menu and from the menu re-launch them as a shortcut ^^.Ss
P
1

You can simply pass null for the image.

Menu.DropDownItems.Add(Text, null, EventHandler);
Pubis answered 15/11, 2016 at 16:23 Comment(0)
S
0

I was having similar issues as Philip Wallace. It's important to note the difference between a ToolStripItem, and a ToolStripMenuItem. I was adding ToolStripItems to a ToolStripMenuItem's DropDownItems, and they would show up, and have all properties set correctly, and accessible in code, but they would not show any text! Switching to a ToolStripMenuItem solved this.

In regards to the original question, I've been using the empty constructor, and setting the fields I needed. (I'm in vb.net with .net 4.0, and it won't let me call New ToolStripMenuItem() since it has a MustInherit tag, so I made this class:

Public Class DynamicToolStripMenuItem
    Inherits ToolStripMenuItem

    Public Sub New(value As Integer, text As String, handler As System.EventHandler)
        MyBase.New()
        Me.Text = text
        Me.Visible = True
        Me.Tag = value
        AddHandler Me.Click, handler
    End Sub
End Class
Sectorial answered 28/3, 2013 at 22:53 Comment(0)
G
0
oMenusSiscon = clsLNUsuario.ObtenerMenu_v2(FrameworkFunctions.USER.Perfil);
bool exists = oMenusSiscon.AsEnumerable().Where(dr => dr.Field<Int32>("Menu_Opcion") == 1).Count() > 0;
DataTable Despacho = oMenusSiscon.AsEnumerable().Where(x => x.Field<Int32>("Menu_Opcion") == 1).Select(x => x).CopyToDataTable();
ToolStripMenuItem oMenuItem = new ToolStripMenuItem();
ToolStripMenuItem itemsSub;
if (exists == true)
{
    DataTable Menu = Despacho.AsEnumerable().Where(x => x.Field<Int32>("Menu_Orden") == 0).Select(x => x).CopyToDataTable();
    oMenuItem.Text = Menu.Rows[0][2].ToString();
    DataTable SubMenu = Despacho.AsEnumerable().Where(x => x.Field<Int32>("Menu_Orden") != 0).Select(x => x).CopyToDataTable();
    for (int i = 0; i < SubMenu.Rows.Count; i++)
    {
        itemsSub = new ToolStripMenuItem();
        itemsSub.Name = SubMenu.Rows[i][4].ToString();
        itemsSub.Enabled = SubMenu.Rows[i][5].ToString() == "A" ? true : false;
        itemsSub.Text = SubMenu.Rows[i][3].ToString();
        itemsSub.Click += new EventHandler(submenu_selected);
        oMenuItem.DropDownItems.Add(itemsSub);

    }

    //myMenu.DropDownItems.AddRange(items);
    menuStrip.Items.Add(oMenuItem);
Geronimo answered 21/6 at 20:5 Comment(1)
Thank you for posting this answer. While this code may answer the question, might you please edit your post to add an explanation as to why/how it works? This can help future readers learn and apply your answer. You are also more likely to get positive feedback (upvotes) when you include an explanation.Embark

© 2022 - 2024 — McMap. All rights reserved.