Dynamically add user control under UpdatePanel in ASP.NET
There are many ways to do this in ASP.NET. I have to say this is a complicated topic for me.
I am not going to tell you all sorts of ways to accomplish this since some guys out there have already done this. And I learned from them. Here is how I like to do it.
I would like to give some important background first.
Page life cycle (simplify) : Init->Load viewstate->Load->Save viewstate->Event Handler
Viewstate : properties and values of your controls, event handler included!
Postback : the page life cycle will be gone through in each postback, so, if you have add some controls dynamically, you have to do the same in the follow up postbacks.
Events : The event handler works with the control’s id, the id is generated according to how you add them, so the ordering of adding controls is crucial.
That is all you need to know. So it would be wise to add you controls at Init stage if it is possible. If you add your controls at Load stage, you will need to add event handlers for them manually. This will be a large load of work that I will avoid. I will now go through how to add control.
It is very likely that you click something or have some events, then you want some controls to appear. The event handler may be your first choice putting in your dynamic add controls code. But this lead to a problem, event handler comes later then Page_Load, don’t even mention Page_Init is even before that. So, I use a work around which is about _doPostBack. Most of the postback involved a Javascript function _doPostBack(). It will pass two parameters to you Page object, which are __EVENTTARGET and __EVENTARGUMENT. __EVENTTARGET is the control that trigger the postback and __EVENTARGUMENT is the value it contains. This is what I do.
public partial class myPage : System.Web.UI.Page
{
public myPage()
{
//add a event handler to the Page Init event
Init += new EventHandler(Page_MyInit);
}
protected void Page_MyInit(object sender, EventArgs e)
{
//get the values of the control Id and it's value
string target = Request.Params.Get("__EVENTTARGET");
string argument = Request.Params.Get(__EVENTARGUMENT);
//add dynamic controls if the event is what you want
if( ...check target and argument...)
{
//I like to use place holder to handle dynamic controls, just add a static place holder
Control uc1 = Page.LoadControl( ...path of your control... );
placeHolder1.Controls.Add(uc1);
}
}
}
This should let you add your controls just fine. If your postback is not using _doPostBack, you can try another approach by Request.Form and loop through it. dev|sushi posts have cover that. And now we need to add those controls in each postback to keep them on the page, I use the dumbest approach which is remembering the controls I have added in the session and check them in Page_Init. Add the following just after the above if {}
if (Session["whatever"] != null && !isFirstTime)
{
... add user control just like before ...
}
There is one thing you need to beware, this make me head ache for a day. remenber don’t do this.
if( ...check target and argument...) { add control a }
if( ...check target and argument...) { add control b }
if( ...check target and argument...) { add control c }
if (Session["whatever"] != null && !isFirstTime) { add control a}
if (Session["whatever"] != null && !isFirstTime) { add control b}
if (Session["whatever"] != null && !isFirstTime) { add control c}
This will mess up your controls ordering, do this instead
if( ...check target and argument...) { add control a }
if (Session["whatever"] != null && !isFirstTime) { add control a}
if( ...check target and argument...) { add control b }
if (Session["whatever"] != null && !isFirstTime) { add control b}
if( ...check target and argument...) { add control c }
if (Session["whatever"] != null && !isFirstTime) { add control c}
As for the viewstate, I recommend you clear it whenever you don’t need it. I simply call Viewstate.Clear() when user click on the menu. Or disable viewstate on dynamic controls by Control.EnableViewState = false when you are using UpdatePanel. Because UpdatePanel will do it for you with javascript. But beware when you design your user controls, give each control and their sub controls a unique id. I think UpdatePanel is restoring values by component’s id which is a common way of ajax. I had a id conflict and it gives me Sys.WebForms.PageRequestManagerServerErrorException.
I hope this helps. ^^