Событие клика для динамически создаваемого массива PictureBox в C#
Я хотел бы помочь с устранением неполадок в этом сегменте кода. Предполагается, что приведенный ниже метод отправляет строку selectedFilePath во вторую форму f2 при каждом нажатии PictureBox. У меня есть массив Picturebox, и каждый из них должен отправить свою строку во вторую форму. У меня проблема в том, что одна и та же строка отправляется каждый раз. vidFilePaths - это массив строк, в котором хранятся пути к файлам. Массив PictureBox создается динамически.
public void launchMovie(PictureBox[] pics, string[] vidFilePaths)
{
for (int i = 0; i < p-1; i++)
{
pics[i].Click += (sender, EventArgs) =>
{
selectedFilePath = "file:///" + vidFilePaths[i];
Form2 f2 = new Form2(selectedFilePath);
this.Hide();
f2.Show();
};
}
}
3 ответа
Вам нужно использовать локальную переменную для хранения i, иначе все события указывают на одно и то же значение (которое p
) к концу метода:
public void launchMovie(PictureBox[] pics, string[] vidFilePaths)
{
for (int i = 0; i < p - 1; i++)
{
int currentIndex = i;
pics[i].Click += (sender, EventArgs) =>
{
selectedFilePath = "file:///" + vidFilePaths[currentIndex];
Form2 f2 = new Form2(selectedFilePath);
this.Hide();
f2.Show();
};
}
}
Вы должны понимать, что когда анонимный метод захватывает локальную переменную (Closure), эта переменная сохраняется в классе, созданном компилятором. Это делается для того, чтобы это значение было сохранено после вашего метода launchMovie
возвращается. Таким образом, все ваши события на самом деле получают доступ к одному и тому же адресу памяти в управляемой куче, которая к тому времени фактически щелкает, и событие возникает i = p
,
Короче говоря, к тому времени, когда вы нажимаете, метод launchMovie
закончился бы и i = p
это значение сохраняется в сгенерированном компилятором классе и используется событием.
Попробуйте создать событие в отдельном методе и посмотрите, как бы вы сохранили значение i
чтобы использовать его, вы бы лучше поняли, что делает компилятор.
Альтернатива:
В качестве альтернативы вы можете использовать pics[i].Tag
Как это:
public void launchMovie(PictureBox[] pics, string[] vidFilePaths)
{
for (int i = 0; i < p - 1; i++)
{
pics[i].Tag = vidFilePaths[i];
pics[i].Click += (sender, EventArgs) =>
{
int index =
selectedFilePath = "file:///" + pics[i].Tag.ToString();
Form2 f2 = new Form2(selectedFilePath);
this.Hide();
f2.Show();
};
}
}
Решение:
public void launchMovie(PictureBox[] pics, string[] vidFilePaths)
{
int i = 0;
for (i = 0; i < p-1; i++)
{
pics[i].Tag = i;
pics[i].Click += (sender, EventArgs) =>
{
int k = Convert.ToInt32((sender as PictureBox).Tag);
Form2 f2 = new Form2("file:///" + vidFilePaths[k]);
this.Hide();
f2.Show();
};
}
}
Когда вы создаете PictureBoxes динамически, вы должны присвоить ему имя и привязать событие здесь, как
for(int i=0; i<yourCount; i++)
{
PictureBox pic=new PictureBox();
pic.Name=i.ToString();
pics.Click += PickClicked;
}
И изменить функциональность в обработчике событий, как это
private void PickClicked(object sender, EventArgs e)
{
PictureBox picBox= sender as PictureBox;
string selectedFilePath = "file:///" + vidFilePaths[Convert.ToInt(picBox.Name)];
Form2 f2 = new Form2(selectedFilePath);
this.Hide();
f2.Show();
}
Надеюсь, поможет!!!