|
Dynamic Loading of User
Control with ViewState Preserved (Live Demo)
Many Programmers stay away from loading User Control dynamically on the Web
Form because of the complexity associated with it's state management and event
handling. It is easy to load a User Control dynamically once you understand the
ASP.Net page creation model. In this article, I would like to show you how easy
it is to implement the dynamic creation of User Control if you simply do it in
the correct way. Let the ASP.Net take care of the complexity while you can
concentrate on your business logic. The article will accompany a Live Demo and
a downloadable complete source codes.
Dynamic
Loading of User Control with ViewState Preserved (Live Demo)
Download
the complete source code DnyCtrl.zip
I was inspired by Victor Garcia's article-
Learning to play "catch-up". I read the other related articles and they
talked about creating user control during the early stage (i.e. Init or Load)
of page creating life cycle. After reading the "catch-up" theory, I have
learned that is not true. You can create the control (dynamically) event after
the page load event and it still maintains the view state.
So, Where (in what event) do we add the control? Well, due to the very nature
of the dynamically added control you have to live with the fact that the
control must be loaded each time the parent page loaded (postback or
non-postback). This is where the tricks begin and I will clarify them soon.
Let me give you a very brief over view of this simple project. I have only one
Web Form (LoadDynamicControl.aspx) and two User Controls (Users.ascx and
Address.ascx). I put the user controls in a sub-directory called Controls.
There are couple of LinkButtons to load the appropriate user control on demand
and I add them to a PlaceHolder on the page. Each of the user control has
couple of text boxes and a button. We need the text boxes to test view state
and we need the button to test event handler on the control. Now, let's take a
look how the pages look like. Just to keep it simple I will only mention the
required HTML tags and the codes but you can get the complete codes in the
download above.
LoadDynamicControl.aspx:
<asp:label
id="Label1"
runat="server"
ForeColor="Blue"
Width="100%">Dynamic Control with view state
<asp:LinkButton
id="lnkUser" runat="server"
CommandArgument="User.ascx"
CommandName="User.ascx">Show User
<asp:LinkButton
id="lnkAddress"
runat="server"
CommandArgument="Address.ascx"
CommandName="Address.ascx">Show Address
<asp:PlaceHolder
id="PlaceHolder1"
runat="server">
|
LoadDynamicControl.aspx.cs:
Controls must be loaded every time the page is loaded. Page_load event would be
an ideal place to load the control. This, however, would not work if the
control must be added in other events such as linkButton click event which
comes after the page_load event. We attempt to load the control in the
page_load event if the control name of the currently loaded control is
available. If the same control is loaded in the page load event we avoid
reloading it in the subsequent event (like LinkButton.Click). It is very
important that we assign the ID attribute of the newly loaded control.
Otherwise, The view state may not work properly.
/******************************************************************
* Dynamically loaded control MUST be loaded every time the page
* is loaded or reloaded. I am using the ViewState to track
* the name of currently loaded control.
* ************************************************************** */
private void Page_Load(object sender, System.EventArgs e)
{
PrintStatus("");
try
{
String ContentID=(String)ViewState[CURRENTLY_LOADED_CONTROL];
if(ContentID!=String.Empty &&ContentID!=null)
{
DynamicLoadControl(ContentID);
}
}
catch(Exception ex)
{
PrintStatus(ex.Message);
}
}
/*******************************************************
* Load the dynamic control provided the control name.
* Control in this example is located in the Controls
* sub-folder of the application.
* It is very important that we assign the ID attribute
* of the newly loaded control. Otherwise, The view state
* may not work properly.
* **************************************************** */
private void DynamicLoadControl(String ControlName)
{
try
{
Control ctrl=this.LoadControl(Request.ApplicationPath +"/Controls/" +ControlName);
ctrl.ID=CURRENTLY_LOADED_CONTROL_ID;
//Clear the Control place holder
PlaceHolder1.Controls.Clear();
//Add the control to the place holder
PlaceHolder1.Controls.Add(ctrl);
/*******************************************************
* The ControlName must be preserved to track the
* currently loaded control.
* **************************************************** */
ViewState["LoadedControl"]=ControlName;
}
catch(Exception ex)
{
throw ex;
}
}
/********************************************************
* This event is fired after the Page_load event. We don't
* want to reload the control of the same control already
* loaded in the page_load event.
* **************************************************** */
private void lnkUser_Click(object sender, System.EventArgs e)
{
/********************************************************
* This event is fired after the Page_load event. We don't
* want to reload the control of the same control already
* loaded in the page_load event.
* **************************************************** */
PrintStatus("");
try
{
ProcessLinkButtonClick(sender);
}
catch(Exception ex)
{
PrintStatus(ex.Message);
}
}
/********************************************************
* This event is fired after the Page_load event. We don't
* want to reload the control of the same control already
* loaded in the page_load event.
* **************************************************** */
private void lnkAddress_Click(object sender, System.EventArgs e)
{
PrintStatus("");
try
{
ProcessLinkButtonClick(sender);
}
catch(Exception ex)
{
PrintStatus(ex.Message);
}
}
private void ProcessLinkButtonClick(object sender)
{
/*********************************************************
* Helper function to process linkButton click handler
* logic.
* ****************************************************** */
try
{
LinkButton lnk=(LinkButton)sender;
String ContentID=lnk.CommandArgument;
if(ContentID!=String.Empty &&ContentID!=null)
{
String AlreadyLoadedContent=(String)ViewState[CURRENTLY_LOADED_CONTROL];
if(AlreadyLoadedContent==null ||AlreadyLoadedContent!=ContentID)
{
DynamicLoadControl(ContentID);
}
}
}
catch(Exception ex)
{
throw ex;
}
}
|
There is no code in the user control other than printing the contents of the
text boxes to a label on click of the button. Button itself is on the user
control.
User.ascx:
First Name:
<asp:TextBox
ID="txtFname"
Runat="server">
Last Name:
<asp:TextBox
ID="txtLname"
Runat="server">
<asp:Label
ID="PrintLabel"
Runat="server">
<asp:Button
ID="btnUser"
Runat="server"
Text="Print User">
|
Address.ascx:
City:
<asp:TextBox
ID="txtCity"
Runat="server">
State:
<asp:TextBox
ID="txtState"
Runat="server">
<asp:Label
ID="PrintLabel"
Runat="server">
<asp:Button
ID="btnAddress"
Runat="server"
Text="Print Address">
|
Have a question or comment? Please visit
Questions & Answers Forum
Prodip K. Saha
The Architect of WWW.ASPNET4YOU.COM.
|