4

I want to have a picture album that when I click any picture it goes to another form to edit that picture.

Now I have some pictureBoxes in the form with the names like PB0, PB1, PB2,...

and a method like this

private void msgShow(int id)
{
    MessageBox.Show(id.ToString());
}

when I add event handler to the two pictureBoxes like this

PB11.Click += new EventHandler((sender2, e2) => msgShow(3));
PB12.Click += new EventHandler((sender2, e2) => msgShow(4)); 

when I click PictureBox1 (PB1) messageBox shows

3

and when i click PictureBox2 (PB2) messageBox shows

4

it was true since I added 18 new pictureBoxes and used this code to do that

for (int i = 0; i <= 19; i++)
{
    ((PictureBox)Form2.ActiveForm.Controls.Find("PB" + i, true)[0]).Click += new EventHandler((sender2, e2) => msgShow(i));
}

now its wrong and when I click each pictureBox messageBox shows

20

but I want to show unique numbers for each PictureBox

TaW
  • 53,122
  • 8
  • 69
  • 111
Arash.Zandi
  • 1,010
  • 2
  • 13
  • 24
  • Have you added PictureBoxes programmatically? – NASSER Aug 15 '15 at 05:38
  • 2
    Read up about *closure*. TLDR: declare an extra int-variable **in the loop**, set it to i, and use that variable in the message box. – Maarten Aug 15 '15 at 05:51
  • 1
    Standard bug: http://blogs.msdn.com/b/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered-harmful.aspx – Hans Passant Aug 15 '15 at 10:08

1 Answers1

2

Try this. Replace your for loop with this one

for (int i = 0; i <= 19; i++)
{
    var pictureBox = (PictureBox) Form2.ActiveForm.Controls.Find("PB" + i, true)[0];
    pictureBox.Tag = i;
    pictureBox.Click += (sender, args) =>
    {            
        msgShow((int)((sender as PictureBox).Tag));
    };
}

EDIT: According to new comments, send class object as

for (int i = 0; i <= 19; i++)
{
    var pictureBox = (PictureBox) Form2.ActiveForm.Controls.Find("PB" + i, true)[0];
    var productInfo = new ProductInfo
    {
        //This class is not mentioned into the question so I set example properties here eg.
       ImageName = "MyImage1.png",
       ImagePath = "C:\\Images\\"
       ...
    };
    pictureBox.Tag = productInfo;
    pictureBox.Click += (sender, args) =>
    {            
        msgShow((ProductInfo)((sender as PictureBox).Tag));
    };
}

And now your msgShow will takes ProductInfo object i-e

private void msgShow(ProductInfo pr)
{
    using(var fr = new FormProduct())
    {      
       fr.pInfo = pr;
       fr.showDialog();
    }
}
NASSER
  • 5,900
  • 7
  • 38
  • 57
  • 1
    This doesn't answer the question. – Maarten Aug 15 '15 at 05:53
  • Thanks Maarten but as a matter of fact i want to send a class instead of int value. private void msgShow(ProductInfo pr) { FormProduct fr= new FormProduct(); fr.pInfo =pr; fr.showDialog(); } and for (int i = 0; i <= 19; i++) { ((PictureBox)Form2.ActiveForm.Controls.Find("PB" + i, true)[0]).Click += new EventHandler((sender2, e2) => msgShow(list[i])); } and a class cannot send within Tag property. – Arash.Zandi Aug 15 '15 at 17:59
  • 1
    @Arash.Zandi You did not mentioned that you want to send class instead of `i`. My answer is according to your question. But I will update it according to your new requirement. – NASSER Aug 16 '15 at 00:59