如何正确地将事件分配给c#Winforms中动态创建的按钮?

问题描述 投票:0回答:1

我的意图是在运行时创建按钮,并为它们订阅一个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++;
    }
}
c# winforms events
1个回答
1
投票

因为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();

或将它们保存到专用集合中(如果流程面板具有其他按钮)

© www.soinside.com 2019 - 2024. All rights reserved.