There are questions that periodically show up in my inbox even though they look wrapped up in different contexts and scenarios. One of these reiterated questions revolves around dynamically built controls. I addressed this topic in an aspnetPRO article and plan to drill down further into it sometime soon.
Latest encarnation of the question regards addition of dynamic controls in a DataGrid templated column. You add the control (say, a Button) and bind it to a Click event handler; next, you run the page. Apparently, it works. If you click and post back, though, any dynamically created controls may disappear and the postback event never fire. First off, why "may"? That's just part of the solution and the problem.
DataGrid-based pages often have a Page_Load like this:
void Page_Load(...) {
if (!IsPostBack)
LoadData();
BindData();
}
In other words, the grid is bound to its data on EVERY postback, regardless of which control really caused the postback. No huge deal, but avoiding that definitely results in clearer and faster code. Not to mention possible interferences with other controls (especially well-written third-party rich controls).
If you don't bind the grid to its data though you just run into the aforementioned troubles with dynamic controls.
Any dynamically added control is a true part of the page when the postback is generated. Among other things, this means that any information that relates to these controls is correctly packed into the HTTP request and received by ASP.NET. Next, the ASP.NET handler in charge of the request—the ProcessRequest method of the page class—instantiates any statically declared control and configures them with viewstate information. Next, it further configures the controls with postback data overwriting viewstate information, if necessary. At this point, if the postback data references a dynamically created control ASP.NET just skips over it and temporarily copies the data in a helper collection of still-to-process postback data. At the end of the initialization step, the ASP.NET page handler fires the Page_Load event. This is a great time, and a formidable hook, for you to manually recreate any dynamically added controls that need be there to correctly process postback data.
After Page_Load returns, the ASP.NET page handler makes a second try on unprocessed postback data. It scans the helper collection to see if now the stored data can be matched to an existing control. If you effectively added any missing control in the mean time, the processing goes smooth and seamless and delivers the expected final behavior. Check the article for further details.