如何动态创建按钮并向其添加事件?

时间:2016-06-25 12:10:02

标签: c# arrays visual-studio events button

我有一系列按钮和标签数组:    Label[] labels = new Label[10]; Button[] but = new Button[10];

在点击另一个按钮时,我想从数组中动态创建新按钮和新标签,我也想要[i]更改标签的tex [i]:

    private void button1_Click(object sender, EventArgs e)
    {
        labels[i] = new Label();
        labels[i].Location = new System.Drawing.Point(0, 15+a);
        labels[i].Parent = panel1;
        labels[i].Text = "Sample text";
        labels[i].Size = new System.Drawing.Size(155, 51);
        labels[i].BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
        a = labels[i].Height + labels[i].Top;

        but[i] = new Button();
        but[i].Text = "-";
        but[i].Location = new System.Drawing.Point(0, labels[i].Height + labels[i].Top);
        but[i].Parent = panel1;
        but[i].Size = new System.Drawing.Size(155, 10);
        but[i].Click += new System.EventHandler(but_Click);
        i++;
    }
    private void but[i]_Click(object sender, EventArgs e)
    {
        labels[i].Text = "Changed Text";
    }

但显然我不能在事件处理程序中放入一个数组,那我该怎么做呢?

3 个答案:

答案 0 :(得分:2)

这样做的一种方法是让你的方法返回一个处理程序而不是 一个处理程序:

private EventHandler but_Click(int i)
{
    return (s, e) => labels[i].Text = "Changed Text";
}

并使用它:

but[i].Click += but_Click(i);

或者内联:

but[i].Click += (s, ea) => labels[i].Text = "Changed Text";

在其中任何一个中发生的是一些编译器魔术来捕获i变量。它等同于此(这也是一种有效的,如果详细的方式):

class MyWrapper {
    private int i;
    public MyWrapper(int i) {
        this.i = i;
    }
    public void TheHandler(object sender, EventArgs e) {
        // TODO: capture the object that owns `labels` also, or this won't work.
        labels[i].Text = "Changed Text";
    }
}

//call with
but[i].Click += new EventHandler(new MyWrapper(i).TheHandler);

答案 1 :(得分:1)

您可以将数组索引作为Tag属性添加到按钮,然后在but_Click中将其拉回。

所以,添加

but[i].Tag = i;

创建按钮。然后更改事件处理程序:

private void but_Click(object sender, EventArgs e)
{
    int buttonIndex = (int)((Button)sender).Tag;
    labels[buttonIndex].Text = "Changed Text";
}

或者将事件处理程序内联:

but[i].Click += (s,e) => { label[i].Text = "Changed Text"; }

使用Tag属性的其他选项,添加:

but[i].Tag = label[i];

...

private void but_Click(object sender, EventArgs e)
{
    Label label = (Label)((Button)sender).Tag;
    label.Text = "Changed Text";
}

这种方法的优点是您在初始创建控件后不依赖于保持数组同步。

答案 2 :(得分:0)

我想这是自我解释的:

public void SomeMehthod()
{
    Button btn1 = new Button();
    Button btn2 = new Button();
    Button btn3 = new Button();

    // Your button-array
    Button[] btns = new Button[]
    {
        btn1,
        btn2,
        btn3
    };

    foreach(Button btn in btns)
    {
        // For each button setup the same method to fire on click
        btn.Click += new EventHandler(ButtonClicked);
    }
}

private void ButtonClicked(Object sender, EventArgs e)
{
    // This will fire on any button from the array
    // You can switch on the name, or location or anything else
    switch((sender as Button).Name)
    {
        case "btn1":
            // Do something
            break;
        case "btn2":
            // Do something
            break;
        case "btn3":
            // Do something
            break;
    }
}

或者,如果你的数组可以访问全球:

Button[] btns = new Button[5];
Label[] lbls = new Label[5];

private void ButtonClicked(Object sender, EventArgs e)
{
    Button clicked = sender as Button;
    int indexOfButton = btns.ToList().IndexOf(clicked);

    // ..IndexOf() returns -1 if nothign is found
    if(indexOfButton > 0)
    {
        lbls[indexOfButton].DoWhatYouWant...
    }
}