【问题标题】:click event for dynamic button inside a datalist数据列表中动态按钮的单击事件
【发布时间】:2021-11-13 16:33:10
【问题描述】:

我有一个 DataList 并正确绑定它。


SqlCommand cmd = new SqlCommand(str_cmd, conn);
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
da.Fill(ds);
dtlst_periodicTask.DataSource = ds;
dtlst_periodicTask.DataBind();
pds.DataSource = ds.Tables[0].DefaultView;
pds.AllowPaging = true;
pds.PageSize = 25;
pds.CurrentPageIndex = CurrentPage;
lnkbtnNext.Enabled = !pds.IsLastPage;
lnkbtnPrevious.Enabled = !pds.IsFirstPage;

还有一些分页代码。 之后,我需要在每一行中动态添加一些按钮,因为按钮的数量不固定。

foreach (DataListItem item in dtlst.Items)
{
    Button btn = new Button();
    btn.Click += new EventHandler(btn_Click);  

    pnl_users.Controls.Add(btn);
}

但是按钮点击事件不起作用。

protected void btn_Click(object sender, EventArgs e)
{
    // code does not fire.
}

当我在 .aspx 页面中放置一个按钮时,可以访问并且它可以工作。

protected void dtlst object source, DataListCommandEventArgs e)
{
}

【问题讨论】:

  • 您必须提供页面背后的代码,因为这很重要您在哪里进行调用

标签: c# asp.net button event-handling datalist


【解决方案1】:

但是你为什么要尝试注入一个按钮?

为什么不首先在标记中包含按钮?我真的看不出布局数据列表的必要性或理由,然后决定使用代码?

只需将一个按钮拖放到数据列表中,就完成了。

这是我们的数据列表 - 我们放入了一个平面简按钮。

<asp:DataList ID="DataList1" runat="server" DataKeyField="ID" >
    <ItemTemplate>
    <div style="border-style:solid;color:black;width:300px;margin-left:25px">

      <div id="mybox" runat="server" style="padding:5px;text-align:right">

            <p>Hotel Name: <asp:TextBox ID="HotelName" runat="server" Text ='<%# Eval("HotelName") %>' /></p>
            <p>First Name: <asp:TextBox ID="FirstName" runat="server" Text ='<%# Eval("FirstName") %>' /></p>
            <p>Last Name: <asp:TextBox ID="LastName" runat="server" Text ='<%# Eval("LastName") %>'    /></p>
            <p>City: <asp:TextBox ID="City" runat="server" Text ='<%# Eval("City") %>'  /></p>
            <p>Province: <asp:TextBox ID="Province" runat="server" Text ='<%# Eval("Province") %>'  /></p>
            Active: <asp:CheckBox ID="Active" runat="server" Checked = '<%# Eval("Active") %>'/>
            <br />
            <asp:Button ID="cmdRow" runat="server" Text="Row click This item" 
            />

        </div>
    </div>
    <div style="height:15px"></div>
</ItemTemplate>
</asp:DataList>

我们要填充的代码如下所示:

   protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
            MyLoadData();
    }
    void MyLoadData()
    {
        using (SqlConnection con = new SqlConnection(Properties.Settings.Default.TEST4))
        {
        string strSQL = "SELECT TOP 3 * FROM tblHotels ORDER BY HotelName";
        using (SqlCommand cmdSQL = new SqlCommand(strSQL, con))
        {
            con.Open();
            DataList1.DataSource = cmdSQL.ExecuteReader();
            DataList1.DataBind();
        }
    }

我们现在有了这个:

现在,让我们连接按钮单击,如下所示:

所以,在上面创建新事件(inteli-sense 提供此选项)。

    protected void cmdRow_Click(object sender, EventArgs e)
    {
        Button btn = (Button)sender;
        DataListItem gRow = (DataListItem)btn.Parent;
        Debug.Print("Row index = " + gRow.ItemIndex.ToString());
        int pkID = (int)(DataList1.DataKeys[gRow.ItemIndex]);
        Debug.Print("Data base PK id = " + pkID.ToString());

        Debug.Print("Hotel name = " + ((TextBox)(gRow.FindControl("HotelName"))).Text);
        Debug.Print("City       = " + ((TextBox)(gRow.FindControl("City"))).Text);
        Debug.Print("--------------------");
    }

输出是这样的:

Row index = 1
Data base PK id = 72
Hotel name = Banff Rocky Mountain Resort
City       = Banff
--------------------

所以,根本不清楚为什么要花费时间、精力和编写代码,而通常情况下,您只需将设计器中的一个好的旧飞机简按钮直接放入数据列表中,并且然后简单地连接一个事件。

编辑:

你可以把马牵到水边——但你能让马喝水吗?

如前所述,您可以注入一个按钮,但我真的但真的但真的不建议这样做。

但是,要使按钮单击事件起作用,您可以这样做:

            HtmlButton btn = new HtmlButton();
            
            btn.InnerText = "Index " + e.Item.ItemIndex;
            btn.Attributes.Add("onclick","__doPostBack('BtnTest2','')");
            btn.ViewStateMode = ViewStateMode.Enabled;
            HtmlGenericControl MyDiv = (HtmlGenericControl)e.Item.FindControl("mybox");
            MyDiv.Controls.Add(btn);

编辑2:

好的,似乎存在持久性问题。

因此,添加必须在页面加载时进行(或者可以更早)。

并且每次回传时都必须重新插入按钮。

现在可以了:

   protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            MyLoadData();
        }
        AddBtns();
    }
    void MyLoadData()
    {
        using (SqlConnection con = new SqlConnection(Properties.Settings.Default.TEST4))
        {
        string strSQL = "SELECT TOP 3 * FROM tblHotels ORDER BY HotelName";
        using (SqlCommand cmdSQL = new SqlCommand(strSQL, con))
        {
            con.Open();
            DataList1.DataSource = cmdSQL.ExecuteReader();
            DataList1.DataBind();
        }
    }
}

    void AddBtns()
    {
        foreach (DataListItem gRow in DataList1.Items)
        {
            Button btn = new Button();
            btn.Text = "Index " + gRow.ItemIndex;
            btn.ID = "Btn" + gRow.ItemIndex;
            btn.Click += new EventHandler(BtnTest3);

            HtmlGenericControl MyDiv = (HtmlGenericControl)gRow.FindControl("mybox");
            MyDiv.Controls.Add(btn);
        }
    }

    void BtnTest3(object sender, EventArgs e)
    {
        Debug.Print("buttn3  click");
    }

注意两个变化:

我们不会仅在 !IsPostback 上添加/注入按钮。

我们每次在页面加载时都注入按钮

我们没有使用 Item 绑定事件。

【讨论】:

  • 感谢您的长回答,但我需要动态添加按钮,因为每行的按钮数量不固定。
  • 我只是在为避免注入按钮提出一个强有力的理由。作为一般规则,点击事件的解析发生在编译时 - 而不是运行时。您可以使用 JavaScript“回发”连接一个按钮,但是按照上面的方法很容易接近。我的意思是,如果它只有 1-4 个按钮,那么隐藏/显示它们并使用行数据绑定事件来设置它(同样少了很多努力)。此外,如果您有更多的按钮,那么它们的位置会发生变化 - UI 和用户没有运动记忆(很难习惯您可以单击一行更改的内容..
  • 如前所述,我说过我很少以这种方式处理事情。您可能已经很好地提出了一个罕见的需求/替代方案,但是如果您可以说有 1-4 个按钮来显示/隐藏,那么您在这里会做得更好,而且代码很少。此外,您计划让这些按钮调用什么代码存根——因为那肯定是编译时代码——你不能为每个按钮注入代码——这是不可能的。那么你打算让这些按钮运行背后的代码是什么?换句话说,这些按钮必须在后面的代码中调用现有的代码存根——对吧?
  • 再次感谢。你能找到错误的代码部分吗?
  • 好吧,会有一个相当长的问题列表 - 您还注意到视图状态,实际上当您单击添加的按钮时,按钮不会持续存在(它们实际上会消失回发。(除非您每次都在回发时运行添加按钮代码)。并且您的示例代码只显示一个按钮 - 到目前为止,我们返回隐藏/显示按钮作为更好的解决方案。正如我所说,你不要提及您需要/将可选添加每行多少个按钮 - 但您的代码只显示一个。但是,我将发布按钮点击工作的设置 - 请参阅我的编辑
猜你喜欢
  • 2012-08-06
  • 1970-01-01
  • 1970-01-01
  • 2020-12-28
  • 2011-09-05
  • 1970-01-01
  • 2014-02-23
  • 1970-01-01
相关资源
最近更新 更多