+1  A: 

I had a similar problem. I think the issue is that dynamically created controls are not kept in view state and don't survive a postback. Here is a comment ripped from my code that describes the solution that I came up with (it may not be the only one, but it worked for me).

This page is used to define a grid dynamically. The user clicks checkboxes to indicate which fields to include on the grid. The logic of this page does two essential things:

(1) It maintains the GridDefinition object that is kept in ViewState. (2) It reconstructs the programatically added controls (essentially everything in the table object) from the GridDefinition in ViewState on each postback. The dynamically added controls are NOT recreated on the postback from ViewState. Indeed, I found that if you don't recreate the controls, their events won't fire. Apparently:

       "The process that matches controls to posted values occurs 
       after page_load completes, so it has to occur just like this 
       if you are to use this way."

When I get a control event indicating some change to the data, I have to reflect that change in the GridDefinition object stored in ViewState. That way, on the NEXT postback, the control can be recreated properly (e.g. a text box indicating the header text for a grid column).

Decker
A: 

When I was researching this issue, it was in the context of Dynamic Menus, and there are a bunch of Google responses that, together, got me through it (because it's a common enough requirement, I guess.) I don't have a summary of the answer, but it might be a helpful place to start (i.e. google for Dynamic Menus .NET). There are several questions here on this site too.

le dorfier
A: 

Ummm... thanks Decker and doofledorfer
I think my brain is failing now... I don't understand...

Anyway I would just "update" the table cells I need to update instead of rewriting the whole rows (is that what you mean by "reflect that change in the GridDefinition object stored in ViewState" Decker?)

A: 

...as another suggestion, isn't binding events after Page_Load too late? and therefore they won't be fired on the postback. maybe something to check out..

Brendan Kowitz
In my asp.net code, I can bind events to dynamically created controls all the way through Page_Load, Page_LoadComplete is too late and bound events will not fire.
Redbeard 0x0A
A: 

Really? That might be why. Thanks Brendan

stackoverflow isnt a discussion forum - if you want to respond to an answer use the comments section :)
flesh
+1  A: 

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)

AndreasKnudsen
A: 

I'm once again reminded why I avoid asp - to me it seems like one level of abstraction too many. But by analogy with javascript, is it possible you're ending up with more than one handler on the event?

le dorfier
+1  A: 

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

flesh
+5  A: 

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";
Buu Nguyen
+1 I believe this is the only difference between my dynamically created controls and the ones specified in this code snippit. I do something like this:`txt.ID = String.Format("txtUserId_{0}", id)`
Redbeard 0x0A
+1  A: 

Re-create dynamically created controls in Page_Init. You won't have access to the viewstate data of a control if you recreate it in Page_Load (viewstate is loaded in PreLoad which happens before Page_Load).

Also, don't forget to assign an ID to the control.

Stefan
A: 

Your Answer given below with entire code

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.ID = "txt1";**

txt.TextChanged += new EventHandler(txt_TextChanged); // Assign event handler

**txt.AutoPostBack = true;**

tc.Controls.Add(txt);
tr.Controls.Add(tc);

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

Table1.Controls.AddAt(0,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(0);**

WriteRows();

}

mojam