【问题标题】:How to make dynamically added buttons clickable如何使动态添加的按钮可点击
【发布时间】:2013-01-07 16:32:37
【问题描述】:

我正在创建一个 C# 应用程序,它从数据库中获取数据,并在一行中动态创建 5 个文本框和一个按钮。

数据库中存在的行数等于创建的文本框和按钮的行数。

我可以成功地创建文本框和按钮的行,文本框甚至能够显示从数据库中获取的数据。

然而,我的问题是生成的按钮在单击时什么也不做,现在这并不意外,因为我还没有创建处理程序来处理单击事件。但是我对如何为再次动态生成的按钮动态创建点击事件处理程序感到困惑。

以下是生成文本框和按钮的代码示例。

for (int i = 3; i <= count; i++)
{
    com.Parameters[0].Value = i;
    using (SqlCeDataReader rd = com.ExecuteReader())
    if (rd.Read())
    {
        pname = (rd["pname"].ToString());
        cname = (rd["cname"].ToString());
        budget = (rd["budget"].ToString());
        advance = (rd["advance"].ToString());
        ddate = (rd["ddate"].ToString());

        TextBox tobj = new TextBox();
        tobj.Location = new Point(10, (40 + ((i - 2) * 20)));
        tobj.Tag = 1;
        tobj.Text = pname;
        tobj.AutoSize = false;
        tobj.Width = 150;
        tobj.ReadOnly = true;
        this.Controls.Add(tobj);

        TextBox tobj1 = new TextBox();
        tobj1.Location = new Point(160, (40 + ((i - 2) * 20)));
        tobj1.Tag = 2;
        tobj1.Text = cname;
        tobj1.AutoSize = false;
        tobj1.Width = 150;
        tobj1.ReadOnly = true;
        this.Controls.Add(tobj1);

        TextBox tobj2 = new TextBox();
        tobj2.Location = new Point(310, (40 + ((i - 2) * 20)));
        tobj2.Tag = 3;
        tobj2.Text = budget;
        tobj2.AutoSize = false;
        tobj2.Width = 100;
        tobj2.ReadOnly = true;
        this.Controls.Add(tobj2);

        TextBox tobj3 = new TextBox();
        tobj3.Location = new Point(410, (40 + ((i - 2) * 20)));
        tobj3.Tag = 4;
        tobj3.Text = advance;
        tobj3.AutoSize = false;
        tobj3.Width = 100;
        tobj3.ReadOnly = true;
        this.Controls.Add(tobj3);

        TextBox tobj4 = new TextBox();
        tobj4.Location = new Point(510, (40 + ((i - 2) * 20)));
        tobj4.Tag = 5;
        tobj4.Text = ddate;
        tobj4.AutoSize = false;
        tobj4.Width = 100;
        tobj4.ReadOnly = true;

        int due = 0;
        due = int.Parse(ddate);
        if (due < 5)
        {
             tobj4.BackColor = System.Drawing.Color.Red;
        }

        this.Controls.Add(tobj4);

        Button button = new Button();
        button.Left = 620;
        button.Tag = i;
        button.Height = 20;
        button.Text = "Details";
        button.Top = (40 + ((i - 2) * 20));
        this.Controls.Add(button);  
    }
}

请给我一些关于如何生成点击事件处理程序的想法。

【问题讨论】:

  • 为什么这个问题被标记为sql-server
  • 因为应用程序正在从 sql server 获取数据,并且我遇到了与控件类似的问题,后来证明是由于错误的 sql 查询引发了异常。跨度>
  • @RickRoy 按钮点击与 sql server 有什么关系?

标签: c# .net winforms


【解决方案1】:

回答部分:

添加这个:

button.Tag = i;
button.Click += handleTheClick;

...

private void handleTheClick(object sender, EventArgs e){
    Button btn = sender as Button;
    int row = (int)btn.Tag;
}

未回答:

您应该重新考虑您的设计。在 2013 年,在数据处理代码中包含坐标是一个非常糟糕的主意,尝试使用 ListView、ListBox、GridView 或更好的 - 切换到 WPF。

【讨论】:

  • 谢谢,这行得通。我将改进我的设计@Sten Petrov,但我是 C# 新手,所以只是尝试一下。感谢您的帮助:)
  • @RickRoy 我知道你是新手,现在是开始学习“新”事物而不是学习历史技术的最佳时机。你不会开始学习 BASIC 或 Fortran 吧?
【解决方案2】:

您需要订阅Click 事件:

button.Click += ... some event handler ...

您可以使用处理程序的方法:

button.Click += MyEventHandlerMethod;

// put this method somewhere in your Form class
void MyEventHandlerMethod( object sender, EventArgs args )
{
  ...

甚至是 lambda:

button.Click += ( s, e ) => HandleClick( ... any parameters here ... );

// put this method somewhere in your Form class
void HandleClick( ... required parameters ... )
{
  ...

作为提示,您可以查看普通表单的.designer.cs 文件以了解事情是如何完成的。

【讨论】:

  • tobj 这里指的是 textbox-es,它们没有 Click 方法。如果“lambda”只是将处理重定向到其他地方,它也不是真正的 lambda,是吗。 lambda 的好处是您可以保持行对象处于活动状态(尽管这会导致内存泄漏,因此请谨慎使用)
  • @StenPetrov 哎呀——现在改为button。使用 lambda 的优点是您可以关闭局部变量并将它们作为参数传递。此外,处理程序方法不必具有EventHandler 签名。
猜你喜欢
  • 1970-01-01
  • 2014-05-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多