我的意图是在运行时创建按钮,并为它们订阅一个click事件处理程序。单击动态创建的按钮后,将取消订阅click事件处理程序,因此click事件仅触发一次。
在运行时,仅当我创建一个按钮并立即单击它时,所需的行为才起作用。如果我创建多个按钮,则只有最后创建的按钮才能取消单击事件的订阅。我错过了什么?
public partial class Form1 : Form
{
Button b;
int counter;
public Form1()
{
InitializeComponent();
}
// create more buttons
private void button1_Click(object sender, EventArgs e)
{
b = new Button();
b.Size = new Size(50, 50);
b.Click += b_Click; // dynamic button click event
this.Controls["flowLayoutPanel"].Controls.Add(b);
}
// dynamic button click eventhandler
void b_Click(object sender, EventArgs e)
{
b.Text = counter.ToString();
b.Click -= b_Click;
counter++;
}
}
因为b
成员将引用上次创建的动态按钮,所以单击任何按钮都将删除b
变量中将最后创建的当前引用按钮的click事件处理程序。
使用sender
访问“当前”按钮的实例并仅从“当前”按钮中删除单击事件处理程序。
void b_Click(object sender, EventArgs e)
{
var button = sender As Button;
button.Text = counter.ToString();
button.Click -= b_Click;
counter++;
}
不要为动态按钮使用私有成员,而是局部变量
private void button1_Click(object sender, EventArgs e)
{
var button = new Button();
button.Size = new Size(50, 50);
button.Click += b_Click;
this.Controls["flowLayoutPanel"].Controls.Add(button);
}
如果需要在某处引用创建的按钮的集合,则可以从添加按钮的流面板的控件中访问它们
var dynamicButtons = .
this.Controls["flowLayoutPanel"].Controls.OfType<Button>().ToList();
或将它们保存到专用集合中(如果流程面板具有其他按钮)