Introduction
In many of our business ASPX applications, there is a need for special UserControls that perform specific functionalities so that they can be easily re-used in the entire application.
There are two ways we can use a UserControl: either we drag it onto the form, or we load it dynamically through the use of LoadControl("MyUserControl.ascx")
.
When we use the second method, we (all?) encounter one major problem: ViewState persistence! Upon postback, when we re-load the control in our CS code, .NET Framework forgets
everything about its previous state. This tiny essay addresses this issue.
Solution!
Straightforward: assign the dynamically loaded control the same ID it had just before the data postback! In fact, .NET Framework retains the state of every user
control (even of those dynamically loaded) and associate them with their programmatic IDs; after a postback, it tries to find the same controls with the same IDs in order
to load their previous state. The whole thing can better be explained through an example :-)
Example
We'll create a simple UserControl which has a TexBox
, we'll also have an ASPX form on which we use this control but in three ways. For this purpose, we'll create
three instances:
- An instance which is already dragged onto the form
- An instance dynamically created through
LoadControl()
- An instance dynamically created through
LoadControl()
with its ID preserved
I have created a simple UserControlViewStateManager
that will help us automatically save/load the dynamically loaded controls and their IDs. The main idea
behind this gadget is to save the ID of the UserControls right after loading them into their parent container and re-creating them after the postback: the best place
for re-creating the controls is the Page_Init
event.
When creating a new user control: just give a unique ID and at the same time, add it to an instance of the UserControlViewStateManager
. Shown below is a snippet:
Control userControl = LoadControl("MyUserControl.ascx");
userControl.ID = (placeHolder2.Controls.Count - 1).ToString();
placeHolder2.Controls.Add(userControl);
ucViewStateManager.AddControl(userControl);
In the Page_Init
event, call ReCreateControlsID()
of the helper class, passing it the container object as a parameter:
ucViewStateManager = new UserControlViewStateManager("SomeUniqueSessionID");
ucViewStateManager.ReCreateControlsID(placeHolder2);
Hope this helps :-) In the demo application, you can find the entire source code.