1

I have a search function which looks up specific users in my OleDb database. For each user, a row in a table is created containing his name, boolean saying if he is an admin or not and a delete button. The delete button is not working as expected, it doesn't execute the method that is linked to it. My code is located in the Search_Click event which executes right after the admin clicks the search button to search for specific users. I tried to place a pre-defined button from my code but in Page_Load instead and it works as expected. How can I get the button to work from the Search_Click as well? Basically, after dynamically creating the LinkButtons according to the user search text and clicking the search button (Search_Click) I need to find a way to register the click event on page load event, I do not know how to do that because the linkbuttons HAVE to be created in the click event of the search button but they also have to be registered via page load.

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);
}

DeleteUser:

 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);
        }
    }
Itay080
  • 164
  • 11
  • There seems to be nothing wrong with this code. You need to provide at least the code for the DeleteUser event. – Sefe Jan 15 '17 at 11:17
  • I have edited my question and it now contains the DeleteUser code :) But as I said, I placed a breakpoint and it doesn't even execute. – Itay080 Jan 15 '17 at 11:28

1 Answers1

2

The event handler for dynamic controls need to be registered during Page_Load / Page_Init events to be triggered (see this link).

So, You have to add your Delete button and its event handler in page_load or init. to find ID of the control which cause postback in Page_Init event, see this


UPDATE:

OK, i add this code to proof it can be done without problems.

To see how it works: create a new Web Form and paste the following HTML & Code-Behinds into it. Then run the app and type some name in Search TextBox (eg: John or Ali) and press Search Button to filter the results.

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

And this is the helper extension method to Get UniqueID of PostBack Control:

// ***********************************************************************
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;
    }

}
Community
  • 1
  • 1
S.Serpooshan
  • 7,608
  • 4
  • 33
  • 61
  • Thanks but I am not really sure how I should proceed from here. I have a mode which is the normal mode, meaning the user is not looking up anything in the database and I also have a mode saying that the user IS looking up someone in the database, how can I know, on page load which mode is currently triggered? How do I know how much entries came up? How do I know the name of the user in the table and the exact location to add that button to on page load? – Itay080 Jan 15 '17 at 11:49
  • as i saw already in your code, with help of this `button.CommandName = (string)reader["uName"];` you know which user shall be deleted. – S.Serpooshan Jan 15 '17 at 11:53
  • Oh, so I only need to register the event in page load, now I get it. But how do I know how many buttons need to be registered? How can I loop through them? I am not asking you to write a code, just for a direction. – Itay080 Jan 15 '17 at 11:59
  • but you already write basic part of such code: `using (OleDbDataReader reader = cmd.ExecuteReader()) ... while (reader.Read()) ... LinkButton button = new LinkButton(); button.Text = "Delete"; ...` – S.Serpooshan Jan 15 '17 at 12:20
  • That's correct, but how do I access it from the page load? – Itay080 Jan 15 '17 at 12:20
  • by the way, why you don't use a simple grid-like codes which is very common in asp.net web forms? (a grid which contain several rows and every row contain a Edit/Delete or so on buttons..._ – S.Serpooshan Jan 15 '17 at 12:21
  • I do not know how to loop trough the controls in the page load event in order to register them. – Itay080 Jan 15 '17 at 12:48
  • I'm wondering why you can't do it! You create a `table` and append it to your placeholder `TableHolder.Controls.Add(table);` – S.Serpooshan Jan 15 '17 at 12:55
  • I already did that, you don't get what I am trying to do. I am trying to register the event of every single LinkButton by looping through the controls, but I do not know how to do that from the page load since I can only register events fromt he page load. – Itay080 Jan 15 '17 at 13:07
  • i have updated the answer to include a sample page with what you want. it takes a time from me to do it ... please take a look and give your feedback. – S.Serpooshan Jan 16 '17 at 12:31
  • Thank you very much S.Serp, I really appreciate your time and effort :) – Itay080 Jan 16 '17 at 13:19