Событие клика для динамически создаваемого массива 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();
}

Надеюсь, поможет!!!

Другие вопросы по тегам