Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

creating delegate new instance of MouseEventHandler

When creating buttons dynamically, i wished to have a new MouseEventHandler. I did this like so,

this.Controls[btnAdd.Name].MouseClick += new MouseEventHandler(generalMethods.generatePopup());

However, as i needed to pass parameters to the event, i made generatePopup to accept an integer which would denote button number (so i could use further). In the past i would have just used an anonymous delegate to pass additional parameters across, but this doesn't seem to work as i want to create a NEW instance, as such;

this.Controls[btnAdd.Name].MouseClick += delegate(object sender, MouseEventArgs e) { new MouseEventHandler( generalMethods.generatePopup(sender, e, i); };

it seems that the error is on new MouseEventHandler. if i take this out, it works fine and i can pass additional data, but because it is not a new instance it doesn't give each button its own event, like so;

this.Controls[btnAdd.Name].MouseClick += new MouseEventHandler(generalMethods.generatePopup());

does anyone know how to work around this? for example to use the anon delegate approach still, but still creating a new instance of the event?

EDIT: hmm, i tried this (parameters pass fine i believe) but it seems as though instead of creating a new mouseeventhandler for each button, it's using the same one for all of the buttons, as i've set a label to test it's getting the right button number, but all of the labels on the popup's are returning the last button number instead of their correct one. any ideas?

EDIT 2: here's my code block for generating buttons:

 for (int i = 0; i <= count && i < 2; i++)
        {

            Button btnAdd = new Button();
            btnAdd.Text = dataTable.Rows[i]["deviceDescription"].ToString();
            btnAdd.Location = new Point(x, y);
            btnAdd.Tag = i;
            btnAdd.Name = "btn" + i.ToString();
            btnAdd.BackColor = Color.Green;

            this.Controls.Add(btnAdd);

            this.Controls[btnAdd.Name].MouseClick += (sender, e) =>
{
    int index = i;
    generalMethods.generatePopup(sender, e, index);
};

and here's my generatePopup method, which is the mouseEventHandler:

public void generatePopup(object sender, MouseEventArgs e, int buttonNumber)
    {
      //  DBConnector mDBConnector = new DBConnector();
      //  DataTable dataTable = mDBConnector.Select("SELECT * FROM devices WHERE deviceID = " + buttonNumber);


        DeviceBreakdownPopup popupDevice = new DeviceBreakdownPopup();
        popupDevice.lblDeviceNo.Text = buttonNumber.ToString();

        PopupWindow popup = new PopupWindow(popupDevice);
        popup.Show(Cursor.Position);

    }

here's an image of what's happening to, just for clarity:

example of error

Here we see both popup usercontrols given the label "2", whereas i need each to have their correct value, "1" and "2".

like image 665
Kestami Avatar asked May 02 '26 12:05

Kestami


1 Answers

Try this:

this.Controls[btnAdd.Name].MouseClick += new MouseEventHandler(
    (sender, evt) => {
        generalMethods.generatePopup()
    }
);

The new MouseEventHandler(...) part is optional - the compiler figures out the parameter types from the left side of the += assignment.

EDIT The problem with your code is that it accesses modified closure. You should make a temp variable from i, and use it inside your lambda to fix the problem.

for (int i = 0; i <= count && i < 2; i++)
    {

        Button btnAdd = new Button();
        btnAdd.Text = dataTable.Rows[i]["deviceDescription"].ToString();
        btnAdd.Location = new Point(x, y);
        btnAdd.Tag = i;
        btnAdd.Name = "btn" + i.ToString();
        btnAdd.BackColor = Color.Green;

        this.Controls.Add(btnAdd);
        var temp = i;
        this.Controls[btnAdd.Name].MouseClick += (sender, e) =>
            {
            int index = temp;
            generalMethods.generatePopup(sender, e, index);
        };
}
like image 106
Sergey Kalinichenko Avatar answered May 05 '26 01:05

Sergey Kalinichenko