Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Event handler not fired for dynamically created controls

I've got this problem with dynamically created TextBox.

When the TextBox is created in PageLoad, it's TextChanged event was fired.
But when I dynamically delete and recreated the TextBox, the TextChanged was not fired.

This is the code:

.aspx file

<body>
    <form id="form1" runat="server">
    <div>

    <asp:Table ID="Table1" runat="server">
      <asp:TableRow>
        <asp:TableCell ColumnSpan="2">Fixed content</asp:TableCell>
      </asp:TableRow>
    </asp:Table>   
    </form>
</body>

.cs file

public partial class test : System.Web.UI.Page
{
  string myText = "a";

  protected void Page_Load(object sender, EventArgs e)
  {
    WriteRows();
  }

  private void WriteRows()
  {
    TableRow tr = new TableRow();

    TableCell tc = new TableCell();
    TextBox txt = new TextBox();
    txt.Text = myText;
    txt.TextChanged += new EventHandler(txt_TextChanged); // Assign event handler
    tc.Controls.Add(txt);
    tr.Controls.Add(tc);

    tc = new TableCell();
    tc.Text = txt.Text;
    tr.Controls.Add(tc);

    Table1.Controls.AddAt(1, tr);
  }

  private void txt_TextChanged(object sender, EventArgs e)
  {
    myText = ((TextBox)sender).Text;
    RedrawTable(); // Delete the row (incl. the TextBox) and rewrite it
  }

  private void RedrawTable()
  {
    Table1.Controls.RemoveAt(1);
    WriteRows();
  }
}

Does anyone have a solution so that the event is always fired?

like image 734
Aximili Avatar asked Nov 21 '08 03:11

Aximili


3 Answers

Event handling is done by ASP.NET by matching up control's ID & the request parameters. In your case, the TextBox created during txtTextChanged() will have an auto ID because you don't specify any explicit ID. That ID will be posted back during the text changed event.

After page load event, ASP.NET will try to find a control with such ID to fire the event for it. Obviously ASP.NET won't be able to find the match because the TextBox created during Page_Load() is different and would have different ID.

To solve this: specify an explicit ID for your textbox:

TextBox txt = new TextBox();
txt.Text = myText;
txt.ID = "txtBox";
like image 195
Buu Nguyen Avatar answered Sep 20 '22 08:09

Buu Nguyen


Try creating the controls in the Page_Init() method ...

like image 25
flesh Avatar answered Sep 22 '22 08:09

flesh


for a postback event to fire, the control that should fire the event needs to be available with the same id and the same data on the postback lifecycle.

If you have static controls (defined in your aspx/ascx/master) and viewstate turned on, then they will be recreated automagically.

If you don't want to use viewstate, or use dynamic controls, you need to databind controls on each page_load, so that the controls are up and running in time for events to fire (happens after Page_load)

if you change the ID of a parent control, or page, you might accidentally throw off the viewstate autobind, as the control IDs contains ancestors IDs. I think you should be safe doing that, so long as you do it in Page_Init (before viewstate is set up)

like image 41
AndreasKnudsen Avatar answered Sep 22 '22 08:09

AndreasKnudsen