1

This is what i want to do:

 .... 
for(i=0;i<=99;i++)
        {
            btn[i].Click += new EventHandler(btn_Clicked,i);
        }
    }

    private void btn_Clicked(object sender, EventArgs e,int i)
    {
        compute((Button)sender, picRetrieved[i]);
    }

Please help. It is showing error. But, I want to send the value of i for further processing. Is there any way to do it?

Thank you.

2 Answers2

4

Thanks to closures and anonymous functions you can do something similar:

for(int i=0;i<=99;i++)
{
    int j = i;
    btn[i].Click += (sender, e) => 
    {
        // Very important! Here use only j, not i!
        compute((Button)sender, picRetrieved[j]);
    };
}

There is a small "problem" (that isn't a problem, it's how they are done) so that you mustn't use the i variable inside the anonymous function, but if you copy it somewhere else (j for example) then you can use j.

Community
  • 1
  • 1
xanatos
  • 109,618
  • 12
  • 197
  • 280
  • I'd like to know what would happen if we use `i`? It's just a variable, isn't it? – Tachyon Feb 27 '15 at 14:16
  • 2
    @Mr.Singh Yes, but there is a single `i` that is shared between the `for` cycle and ALL the anonymous functions. What happens is that at the end of the `for` cycle `i == 100`, so all anonymous functions use 100 as the value (this if they are called outside the for cycle, that should happen because they are events... If they are called before the end of the for cycle they have the "current" `i` value) – xanatos Feb 27 '15 at 14:18
  • Its showing error in (sender, e) What to do? I simply want to call a function on button click. – Kountay Dwivedi Feb 27 '15 at 14:18
  • 3
    @Mr.Singh What will happen is that each event handler will have a reference to the *same* variable `i`. So by the time the event handlers get called, the value in that variable will most likely be 100. By making a new variable inside the loop, each handler gets a reference to a different version of the variable `j`. This is because `j` is scoped to the inside of the loop and each iteration introduces a different variable. – Kyle Feb 27 '15 at 14:22
  • @KountayDwivedi Missing a ; at the end of a } . Fixed – xanatos Feb 27 '15 at 14:22
  • Thanks xanatos and @Kyle for the explanation. I really appreciate that. – Tachyon Feb 27 '15 at 14:27
  • Thanks a lot. Dunno what is (sender, e) but it worked. Thanks again :) Just changed (sender, e) to ( ) – Kountay Dwivedi Feb 27 '15 at 14:36
  • 1
    @KountayDwivedi `(sender, e)` are the parameters. In this particular case it's equivalent to writing `(object sender, EventArgs e)` – xanatos Feb 27 '15 at 14:38
2

You can't. The signature of the event handler is fixed, you can't change it.

In this case, you could use an anonymous delegate to get what you want.

for(i = 0; i <= 99; i++)
{
    int dummy = i;
    btn[i].Click += delegate(object sender, EventArgs e)
        {
            compute(btn[dummy], picRetrieved[dummy]);
        }
}

Another option is to 'tag' the button:

for(i = 0; i <= 99; i++)
{
    btn[i].Click += btn_Clicked;
    btn[i].Tag = i;
}

private void btn_Clicked(object sender, EventArgs e,int i)
{
    Button b = (Button)sender;
    int i = (int)b.Tag;

    compute(b, picRetrieved[i]);
}
Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325