【问题标题】:Problems with dynamic buttons in ASP.NET (C#)ASP.NET (C#) 中的动态按钮问题
【发布时间】:2023-03-25 04:55:02
【问题描述】:

我有一个搜索功能,可以在我的 OleDb 数据库中查找特定用户。对于每个用户,都会在表中创建一行,其中包含他的姓名、布尔值表示他是否是管理员以及一个删除按钮。删除按钮没有按预期工作,它不执行链接到它的方法。我的代码位于 Search_Click 事件中,该事件在管理员单击搜索按钮以搜索特定用户后立即执行。 我试图从我的代码中放置一个预定义的按钮,但在 Page_Load 中,它按预期工作。我怎样才能让按钮也从 Search_Click 工作? 基本上,在根据用户搜索文本动态创建 LinkBut​​tons 并单击搜索按钮 (Search_Click) 之后,我需要找到一种方法来在页面加载事件上注册 click 事件,我不知道该怎么做,因为 linkbuttons 必须在搜索按钮的点击事件中创建,但它们也必须通过页面加载进行注册。

using (OleDbDataReader reader = cmd.ExecuteReader())
{
    Table table = new Table();
    TableRow row = new TableRow();
    TableCell cell = new TableCell();
    Label label = new Label();
    while (reader.Read())
    {
        row = new TableRow();
        cell = new TableCell();
        label = new Label();

        label.Text = reader.GetString(0);
        cell.Controls.Add(label);
        cell.BorderStyle = BorderStyle.Solid;
        row.Cells.Add(cell);

        cell = new TableCell();
        label = new Label();

        label.Text = reader.GetBoolean(1).ToString();
        cell.Controls.Add(label);
        cell.BorderStyle = BorderStyle.Solid;
        row.Cells.Add(cell);

        cell = new TableCell();
        LinkButton button = new LinkButton();

        button.Text = "Delete";
        button.ID = (string) reader["uName"];
        button.CommandName = (string)reader["uName"];
        button.Click += new EventHandler(DeleteUser);

        cell.Controls.Add(button);
        cell.BorderStyle = BorderStyle.Solid;
        row.Cells.Add(cell);

        table.Rows.Add(row);
    }
    table.Style.Add(HtmlTextWriterStyle.MarginLeft, "auto");
    table.Style.Add(HtmlTextWriterStyle.MarginRight, "auto");
    TableHolder.Controls.Add(table);
}

删除用户:

 protected void DeleteUser(object sender, EventArgs e)
    {
        try
        {
            LinkButton button = (LinkButton)sender;
            string path = Server.MapPath(@"App_Data/ArcadeDatabase.accdb");
            using (OleDbConnection con = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + path + "; Persist Security Info = False;"))
            {
                try
                {
                    con.Open();
                }
                catch(Exception ex)
                {
                    helper.Log("OleDbError", ex.Message);
                }
                if(con.State == System.Data.ConnectionState.Open)
                {
                    using (OleDbCommand cmd = new OleDbCommand("DELETE * FROM ArcadeDatabase WHERE uName ='" + button.CommandName + "';", con))
                    {
                        try
                        {
                            cmd.ExecuteNonQuery();
                        }
                        catch (Exception ex)
                        {
                            helper.Log("OleDbError", ex.Message);
                        }
                    }
                }
                con.Dispose();
            }
            path = "";
        }
        catch (Exception ex)
        {
            helper.Log("Admin", ex.Message);
        }
    }

【问题讨论】:

  • 这段代码似乎没有问题。您至少需要提供 DeleteUser 事件的代码。
  • 我已经编辑了我的问题,它现在包含 DeleteUser 代码:) 但正如我所说,我放置了一个断点,它甚至没有执行。

标签: c# asp.net


【解决方案1】:

动态控件的事件处理程序需要在Page_Load/Page_Init事件期间注册才能触发(see this link)

因此,您必须在 page_load 或 init 中添加删除按钮及其事件处理程序。在 Page_Init 事件中查找导致回发的控件的 ID,see this


更新:

好的,我添加此代码以证明它可以毫无问题地完成。

要查看它是如何工作的:创建一个新的Web Form 并将以下 HTML 和 Code-Behinds 粘贴到其中。然后运行应用程序并在Search TextBox 中输入一些名称(例如:JohnAli),然后按Search Button 过滤结果。

public partial class _Default : Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        string searchName = "";
        if (SearchTextBox.Text != "") //if (this.GetPostBackControlUniqueID() == Search.UniqueID) //Search button is clicked! 
        {
            searchName = SearchTextBox.Text;
        }
        addTable(searchName);
    }

    void addTable(string searchName)
    {
        string[] data = new[] { 
             "John, false, usrJohn"
            ,"Alex, false, usrAlex"
            ,"Ali,  true,  usrAli" 
        };

        //using (OleDbDataReader reader = cmd.ExecuteReader())
        //{
            Table table = new Table(); table.CellPadding = 10;
            TableRow row;
            TableCell cell;
            Label label;

            foreach(string dataItem in data) //while (reader.Read())
            {
                string[] reader = dataItem.Split(',');
                if (reader[0].IndexOf(searchName, StringComparison.OrdinalIgnoreCase) < 0) continue; //search not found (in real app, you use sql where clause for this, but this is just for test)

                row = new TableRow();
                cell = new TableCell();
                label = new Label();

                label.Text = reader[0].Trim(); //reader.GetString(0);
                cell.Controls.Add(label);
                cell.BorderStyle = BorderStyle.Solid;
                row.Cells.Add(cell);

                cell = new TableCell();
                label = new Label();

                label.Text = reader[1].Trim(); //reader.GetBoolean(1).ToString();
                cell.Controls.Add(label);
                cell.BorderStyle = BorderStyle.Solid;
                row.Cells.Add(cell);

                cell = new TableCell();
                LinkButton button = new LinkButton();

                button.Text = "Delete";
                string uName = reader[2].Trim();
                button.ID = uName; //(string)reader["uName"];
                button.CommandName = uName; //(string)reader["uName"];
                button.Click += new EventHandler(DeleteUser);

                cell.Controls.Add(button);
                cell.BorderStyle = BorderStyle.Solid;
                row.Cells.Add(cell);

                table.Rows.Add(row);
            }

            table.Style.Add(HtmlTextWriterStyle.MarginLeft, "auto");
            table.Style.Add(HtmlTextWriterStyle.MarginRight, "auto");

            TableHolder.Controls.Add(table);
        //} //end using OleDbDataReader reader
    }

    protected void Search_Click(object sender, EventArgs e)
    {
        //addTable(SearchTextBox.Text); //already done in Page_Load
    }

    protected void DeleteUser(object sender, EventArgs e)
    {

        LinkButton button = (LinkButton)sender;
        //using (OleDbCommand cmd = new OleDbCommand("DELETE * FROM ArcadeDatabase WHERE uName ='" + button.CommandName + "';", con))
        string sql = "DELETE * FROM ArcadeDatabase WHERE uName ='" + button.CommandName + "';";
        //execute the sql ... (in real app)

        TableHolder.Controls.Add(new LiteralControl("The sql was: " + sql));
    }

    protected void Button1_Click(object sender, EventArgs e)
    {
        Label1.Text = DateTime.Now.ToString("HH:mm:ss");
    }


} //end class

这是获取UniqueIDPostBack 控件的辅助扩展方法:

// ***********************************************************************
public static class MyWebPageExtensions
{

    public static string GetPostBackControlUniqueID(this Page page)
    {
        if (!page.IsPostBack)
            return string.Empty;

        Control control = null;

        string controlName = page.Request.Params["__EVENTTARGET"]; //this method works only for link buttons which use javascript: __doPostBack(...) and not input type=submit buttons. Note: it is also available in Request.Form collection but this doesn't require to loop over Form.
        if (!String.IsNullOrEmpty(controlName))
        {
            control = page.FindControl(controlName);
        }
        else
        {
            // __EVENTTARGET is null, the control is a button (not javascript linkButton), we need to iterate over the form collection to find it
            foreach (string id in page.Request.Form)
            {
                // handle ImageButton they having an additional "quasi-property" in their Id which identifies mouse x and y coordinates
                if (id.EndsWith(".x") || id.EndsWith(".y"))
                {
                    string id2 = id.Substring(0, id.Length - 2);
                    control = page.FindControl(id2);
                }
                else
                {
                    control = page.FindControl(id);
                }

                if (control is IButtonControl) break;

            }
        }

        return control == null ? String.Empty : control.UniqueID;
    }

}

【讨论】:

  • 谢谢,但我不确定我应该如何从这里开始。我有一个模式是正常模式,这意味着用户没有在数据库中查找任何内容,我也有一个模式说用户正在数据库中查找某人,我怎么知道在页面加载时是哪种模式当前触发?我怎么知道有多少条目出现了?我如何知道表格中用户的姓名以及在页面加载时将该按钮添加到的确切位置?
  • 正如我已经在您的代码中看到的那样,借助 button.CommandName = (string)reader["uName"]; 您知道应该删除哪个用户。
  • 哦,所以我只需要在页面加载中注册事件,现在我明白了。但是我怎么知道需要注册多少个按钮呢?我怎样才能遍历它们?我不是要你写代码,只是为了一个方向。
  • 但您已经编写了此类代码的基本部分:using (OleDbDataReader reader = cmd.ExecuteReader()) ... while (reader.Read()) ... LinkButton button = new LinkButton(); button.Text = "Delete"; ...
  • 没错,但是如何从页面加载中访问它?
猜你喜欢
  • 1970-01-01
  • 2018-10-10
  • 2011-08-17
  • 2011-08-21
  • 1970-01-01
  • 2011-08-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多