Как убрать повторение кода обработчиков событий элементов управления?
Доброго времени суток.
Прошу помощи в усмирении моего внутреннего перфекциониста. Негодует он от того, что я дублирую код. Сейчас поясню.
На форме я динамически создаю в функции три элемента управления: Panel, PictureBox и Label. Последние два относятся к только что созданному первому элементу управления как дочерние.
private void ConstructUser(int uidx, string name, string avatar_path);
По нажатию на любой из этих элементов управления я желаю выполнить некоторый код, который использует локальные переменные uidx и name. Я не смог придумать никакой иной реализации, кроме как использование лямбда обработчиков событий:
Panel ctrl = new Panel();
// ...
ctrl.MouseClick += (sender, e) =>
{
if (e.Button == MouseButtons.Left)
{
ShowUserInfo(uidx, name); // ShowUserInfo - еще одна функция формы.
}
};
В этом то и проблема. Событие происходит только когда я нажимаю на панель ctrl (менее 5% от общего покрытия нажимаемой зоны; 95% занимают дочерние элементы управления).
- Я не могу сказать дочерним элементам управления панели
ctrl, что желаю получать их событияMouseClickв обработчикеMouseClickэлементаctrl. - Я не могу использовать функцию формы как обработчик так как мне нужен доступ к локальным переменным
uidxиname, существующим только в контексте функции-создателеConstructUser. - Я не могу панели
ctrlдописать свои дополнительные данные, которые содержали бы локальные переменныеuidxиname, чтобы использовать функцию формы. Писать обертку классаPanelсчитаю несуразным. Уверен, самPanelимеет такие возможности, но я о них и близко не в курсе. - Я не могу создать лямбда функцию как переменную. Тут уже сказывается малый опыт на c#. Лямбда функциям как переменным обязательно необходимо возвращаемое значение. Нет тут его.
В итоге всего мне пришлось дублировать код обработчика для всех создаваемых элементов управления.
ctrl.MouseClick += (sender, e) =>
{
if (e.Button == MouseButtons.Left)
{
ShowUserInfo(uidx, name);
}
};
_myPictureBox1.MouseClick += (sender, e) =>
{
if (e.Button == MouseButtons.Left)
{
ShowUserInfo(uidx, name);
}
};
_myLabel1.MouseClick += (sender, e) =>
{
if (e.Button == MouseButtons.Left)
{
ShowUserInfo(uidx, name);
}
};
Этой сейчас мне не страшно: три строчки кода повторить три раза. А что будет в бедующем? А тогда я буду иметь ваши ответы.
Мне было бы интересно увидеть ответ решения на любой или на каждый из перечисленных пунктов выше. Любой из них решает мою проблему, а чем больше - тем вариативнее станет мой выбор программного решения.
Спасибо за внимание.
Приложение А
Всего выше хватит для ответа, но приведу код фигурируемых тут функций из главной формы Form1. Это на случай, если вы захотите полностью повторить мою ситуацию.
private void ShowUserInfo(int uidx, string name)
{
Form2 _ = new Form2(uidx, name); // Ошибка? Можете просто удалить тело этой функции.
_.Show();
}
private int offset = 0; // px; c++ like static local variable...
private void ConstructUser(int uidx, string name, string avatar_path)
{
// CONTROLS:
int cx_w = SystemInformation.FixedFrameBorderSize.Width * 2 + SystemInformation.VerticalScrollBarWidth;
Panel ctrl = new Panel();
ctrl.Parent = panel1; // Ошибка? Обязан быть. Не забудьте свойство AutoScroll = true.
ctrl.BorderStyle = BorderStyle.FixedSingle;
ctrl.Location = new Point(0, offset);
ctrl.Size = new Size(ctrl.Parent.Width - cx_w, 64);
ctrl.Font = ctrl.Parent.Font;
ctrl.Parent.Controls.Add(ctrl);
offset += ctrl.Size.Height + 12; // h + padding
PictureBox avatar = new PictureBox();
avatar.Parent = ctrl;
avatar.BorderStyle = BorderStyle.None;
avatar.Location = new Point(0, 0);
avatar.SizeMode = PictureBoxSizeMode.StretchImage;
avatar.Size = new Size(64, 64);
avatar.Image = Image.FromFile(avatar_path);
avatar.Parent.Controls.Add(avatar);
Label nm = new Label();
nm.Parent = ctrl;
nm.TextAlign = ContentAlignment.MiddleLeft;
nm.Location = new Point(avatar.Size.Width + 6, 0);
nm.Size = new Size(nm.Parent.Width - avatar.Width - 12 - SystemInformation.BorderSize.Width * 2, nm.Parent.Height);
nm.Font = nm.Parent.Font;
nm.Text = name;
nm.Parent.Controls.Add(nm);
// COLORS:
avatar.BackColor = Color.Bisque;
ctrl.BackColor = Color.Coral;
nm.BackColor = Color.Silver;
// EVENTS:
ctrl.MouseClick += (sender, e) =>
{
if (e.Button == MouseButtons.Left)
{
ShowUserInfo(uidx, name);
}
};
avatar.MouseClick += (sender, e) =>
{
if (e.Button == MouseButtons.Left)
{
ShowUserInfo(uidx, name);
}
};
nm.MouseClick += (sender, e) =>
{
if (e.Button == MouseButtons.Left)
{
ShowUserInfo(uidx, name);
}
};
}
Ответы (1 шт):
Вариант с локальной функцией
void myHandler (object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
ShowUserInfo(uidx, name);
}
};
// EVENTS:
ctrl.MouseClick += myHandler;
avatar.MouseClick += myHandler;
nm.MouseClick += myHandler;
Вариант с лямбдой
var myHandler = new MouseEventHandler((object sender, MouseEventArgs e)=>
{
if (e.Button == MouseButtons.Left)
{
ShowUserInfo(uidx, name);
}
});
// EVENTS:
ctrl.MouseClick += myHandler;
avatar.MouseClick += myHandler;
nm.MouseClick += myHandler;