hey guys,

this is what i want to do, i already have a ToolStripMenuItem with a few DropDownItems with events.

i would then like to loop through these Items like such:

foreach (object menuitem in tlstrpmnuitmFunctionHeader.DropDownItems)
{
}

and then assign these items to a ContextMenu. it would really cut down the codding length a lot of i can somehow retrieve the events assigned to the tools strip menu items and assign them to the ContextMenu items.

i've done something like this, but its obviously wrong!

foreach (object menuitem in tlstrpmnuitmFunctionHeader.DropDownItems)
{
RowHeaderMenu.MenuItems.Add(((ToolStripMenuItem)menuitem).Name, ((ToolStripMenuItem)menuitem).Click); 
}

what i want is to get the onClick event assigned to the ToolStripMenuItem to be assigned to the RowHeaderMenu item as well. i'm currently doing the following, which is assign each event to the ContextMenu item one by one:

RowHeaderMenu.MenuItems.Add(((ToolStripMenuItem)menuitem).Text, Menu1_Click);
RowHeaderMenu.MenuItems.Add(((ToolStripMenuItem)menuitem).Text, Menu2_Click);

and on...and on...

I dont believe you can retrieve deligates assigned to an event, however, i would have thoguht you could cheat! And make an anonymous method that would work something like:

RowHeaderMenu.MenuItems.Add(((ToolStripMenuItem)menuitem).Name, delegate(object ssender, EventArgs se) { ((ToolStripMenuItem)menuitem)..PerformClick(); });

thanks for the reply! however i don't quite understand what you're doing there. can you please elaborate?

by the way i tried the above segment out and all items fire the last item's event.

What Im doing is creating an event on the fly and telling it to click the toolmenuitem in question.

The only difference between you and me is I assigned a variable to my item, so rather than keep referencing ((ToolStripMenuItem)menuitem) I had assigned it as a variable, try that, as it most certainly does and should work.

alright! thanks! that makes sense.

but the problem still persists, what i meant was after i use your code segment, the RowHeaderMenu items that have been assigned the delegate events all fire the same event, which is the ToolStripMenuItem's last item's perform click event.

Ok did you try instead of repeatdly referencing the (ToolStripMenuItem)menuitem) make a variable in your foreach loop and use that?

You can do a test app with buttons and text boxes and it most certainly will and should work

ok so i'm really confused now. what difference does a variable make? or i've misunderstood what you're trying to tell me. anyway this is what i came out with. the example you gave really made sense, but i don't know why it kept referencing the last event only.

ToolStripMenuItem tsmi;
            foreach (object menuitem in tlstrpmnuitmFunctionHeader.DropDownItems)
            {
                if (menuitem is ToolStripMenuItem)
                {
                    tsmi = (ToolStripMenuItem)menuitem;
                    RowHeaderMenu.MenuItems.Add(tsmi.Text, delegate(object ssender, EventArgs se) { tsmi.PerformClick(); });
                    RowHeaderMenu.MenuItems[RowHeaderMenu.MenuItems.Count - 1].Name = tsmi.Name;
                    RowHeaderMenu.MenuItems[RowHeaderMenu.MenuItems.Count - 1].Enabled = false;
                }
            }

Does it work now?
a variable is a direct reference to a specific item.. where as the non variable kind is a reference to something thats changing. if that makes any sense

no it doesn't and its weird! i used the above coding, i even added a

tsmi = new ToolStripMenuItem();

before assigning anything to it.

it still fires the last item's event.

sure. here you go.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Skybound.FreeStyle;

namespace testing
{
    public partial class Form4 : TestInherited
    {
        ContextMenu cm1;
        ToolStripMenuItem toolstripmenuitem;
        public Form4()
        {
            InitializeComponent();
            cm1 = new ContextMenu();
            this.Load += new EventHandler(Form4_Load);
            tabPage1.MouseUp +=new MouseEventHandler(tabPage1_MouseUp);
            strip1ToolStripMenuItem1.Click += new EventHandler(strip1ToolStripMenuItem1_Click);
            strip2ToolStripMenuItem.Click += new EventHandler(strip2ToolStripMenuItem_Click);
        }

        void strip2ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MessageBox.Show("2");
        }

        void strip1ToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            MessageBox.Show("1");
        }

        void tabPage1_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
                cm1.Show(tabPage1, e.Location);
        }

        void Form4_Load(object sender, EventArgs e)
        {
            foreach (object dropdownitem in strip1ToolStripMenuItem.DropDownItems)
            {
                if (dropdownitem is ToolStripMenuItem)
                {
                    toolstripmenuitem = new ToolStripMenuItem();
                    toolstripmenuitem = (ToolStripMenuItem)dropdownitem;
                    cm1.MenuItems.Add(toolstripmenuitem.Name, delegate(object ssender, EventArgs se) { toolstripmenuitem.PerformClick(); });
                }
            }
        }
    }
}

hmm, try dropping the

toolstripmenuitem = new ToolStripMenuItem();

As you are creating space you dont need.. Other than that, that should work..I'll experiment more when I get to work

no can do. tried that but it still doesnt work. anyway i posted the code segment in another forum and i got this reply.

As for that code, I now see what you were trying to achieve, or at least what that code is supposed to do. It uses an anonymous method as the Click event handler for the new MenuItem. The thing is, in that anonymous method you refer to the toolstripmenuitem variable. Once you've been through the loop you've got multiple event handler all calling the PerformClick method of the ToolStripMenuItem object that that variable refers to NOW, not the one it referred to when they were created. Of course the variable refers to the last item at the end of the loop, so all event handlers will reference the last item.

but i couldn't really make sense of it.

Hmm, I get what they said, but thats not entirely true. As a new variable is created each time the loop goes through - which is why the variable had to be inside the loop not outside - otherwise Id wholeheartedly agree.

For example:

Crearte an empty app
Create 2 buttons
Create an edit box

in the event of the first button do

String a = textBox1.Text;
button2.click += deligate (object ssender, EventArgs se) { messagebox.Show(a); };

enter a click button1, enter b, click button1

click button2

you'll now get a and then b in messageboxes. thus showing that the variables stayed within the anonymous methods.

Im almost possitive ive used this to keep hold of random objects

Im now at work I got a bit of stuff to do - as much as you guys might find it funny, Im not currently employed as a developer :P I have been, was for many years, but not currently.. I do something else. It needs doing, and after all they pay me to do it..

You give that a go, and see what I mean, and I'll try and work out a way round it.. There has to be one!

OK

its working for me so theres something odd going on.

I made 2 forms, (I didnt rename anything its a hack its ugly and you just have to go with it)

first form is blank!
second form has 4 buttons on
and the following code

private void button1_Click(object sender, EventArgs e)
        {
            MessageBox.Show("button1");
        }

        private void button2_Click(object sender, EventArgs e)
        {
            MessageBox.Show("button2");
        }

        private void button3_Click(object sender, EventArgs e)
        {
            MessageBox.Show("button3");
        }

        private void button4_Click(object sender, EventArgs e)
        {
            MessageBox.Show("button4");
        }

So..

My code then in the creation of form1 was..

Form2 f2 = new Form2();
            f2.Show();
            foreach (Button b in f2.Controls)
            {
                Button x = b;
                Button nb = new Button();
                nb.Name = b.Name;
                nb.Parent = this;
                nb.Top = b.Top;
                nb.Left = b.Left;
                nb.Height = b.Height;
                nb.Width = b.Width;
                nb.Text = b.Text;
                nb.Click += delegate(object ssender, EventArgs se) { Text = ((Button)x).Text; x.PerformClick(); };
            }

So
on running, I get 2 forms, both with 4 buttons

If I click button4 on form1 (the button made on the fly) it pops up button4, just like it would if I had clicked button4 on form2, similarly i get button1 if I click button1.

So the process should be working as I described. and expected..

Make the test app for yourself, it should work..

i think its my fault. there some subtle differences that i overlook. here's what i did:

ToolStripMenuItem menuItem;
      foreach (object item in strip1ToolStripMenuItem.DropDownItems)
      {
          if (item is ToolStripMenuItem)
          {
              menuItem = (ToolStripMenuItem)item;
              cm1.MenuItems.Add(menuItem.Text, delegate(object ssender, EventArgs se) { menuItem.PerformClick(); });
          }
      }

i should be doing this:

foreach (object item in strip1ToolStripMenuItem.DropDownItems)
      {
          if (item is ToolStripMenuItem)
          {
              ToolStripMenuItem menuItem = (ToolStripMenuItem)item;
              cm1.MenuItems.Add(menuItem.Text, delegate(object ssender, EventArgs se) { menuItem.PerformClick(); });
          }
      }

problem solved. thanks again.

Ah!! I could have sworn your code showed it inside the loop (I did remember saying create a variable in the loop)

Well, happy now.. Dont forget to mark it as solved

yeah i think i just forgot to move it back in after some testing. well thanks.

This question has already been answered. Start a new discussion instead.