(В названии может быть ужасная формулировка)
У меня есть массив меток, я хочу добавить ввод мыши и оставить события на этих метках.
Эти ярлыки создаются программно:
Label [] lblData = new Label[255];
int calcLoc = 0;
for (int i = 0; i <= 200; i++)
{
calcLoc = 25 * i;
lblData[i] = new Label();
lblData[i].Location = new Point(10, calcLoc);
lblData[i].Text = "Test " + i;
InfoPanel.Controls.Add(lblData[i]);
}
Что я пробовал: Установка события в цикле (явно не сработало)
lblData[i].MouseEnter += (sender, e) => {lblData[i].BackColor = Color.LightBlue;};
Установка события перед циклом (подумал, что у этого может быть шанс)
lblData[].MouseEnter += (sender, e) => {lblData[].BackColor = Color.LightBlue;};
Ни работать.
Это WindowsForm или WPF?
Я предполагаю, что каждый берет ссылку на i, поэтому получает последнее значение i. Верно? Вы можете либо взять локальную копию i в цикле (например, var j = i;
), либо объявить метод для обработки события и распаковать sender
обратно в объект метки.
в качестве примечания .. вместо создания 255 элементов управления и обработчиков событий вы, вероятно, можете использовать один элемент управления и один обработчик событий. Например, ListBox или DataGridView можно сделать похожими на ярлыки, изменив цвет и другие свойства.
@Slai Я добавил код для единственного обработчика событий для всех элементов управления. Однако не могу говорить о большом количестве элементов управления.
Как насчет этого?
Label[] lblData = new Label[255];
int calcLoc = 0;
for (int i = 0; i <= 200; i++)
{
calcLoc = 25 * i;
Label label = new Label();
label.Location = new Point(10, calcLoc);
label.Text = "Test " + i;
label.MouseEnter += (sender, e) =>
{
label.BackColor = Color.LightBlue;
};
InfoPanel.Controls.Add(label);
lblData[i] = label;
}
Или даже это:
Label[] lblData =
Enumerable
.Range(0, 201)
.Select(i =>
{
var calcLoc = 25 * i;
Label label = new Label();
label.Location = new Point(10, calcLoc);
label.Text = "Test " + i;
label.MouseEnter += (sender, e) =>
{
label.BackColor = Color.LightBlue;
};
InfoPanel.Controls.Add(label);
return label;
})
.ToArray();
Вы можете использовать один метод и параметр sender
. Вот код с минимальными изменениями. Вместо этого у вас может быть отдельный статический метод для всех событий и просто проверить sender
.
lblData[i].MouseEnter += (sender, e) => {((Label)sender).BackColor = Color.LightBlue;};
Более безопасная и немного более быстрая версия, на которую все экземпляры Label
могут подписаться ниже.
Статические методы лучше для производительности по причинам, которые я не буду вдаваться в подробности: вы избегаете использования замыканий, и это гарантирует, что событие было инициировано Label
.
private static void label_MouseEnter(object sender, EventArgs e)
{
var label = sender as Label;
if (label == null)
return;
label.BackColor = Color.LightBlue;
}
Прокомментируйте, пожалуйста, голоса против, чтобы я мог решить любые проблемы.
Из всех советов это решение сработало для меня лучше всего, поэтому оно было помечено как правильное. У меня не было проблем, и я работал немного быстрее, чем ожидал. Спасибо за помощь!
Без проблем. Я заметил, что производительность немного улучшится. Не забудьте либо избавиться от элементов управления, либо отказаться от подписки на событие, чтобы предотвратить возможную утечку памяти.
Почему «явно не сработает» ??