Retaining State for Dynamically Created Controls in ASP.NET applications

When creating controls on the fly on your ASP.NET pages viewstate is a bit hard to track. Learn how it works and how to help your application remembers where to put what.

Introduction

When dynamically adding controls to an ASP.NET page in runtime the object
references are lost at postback because they have no handle in the codebehind.
The values entered by the user is not availible when accessing these objects
after postback, and they seem empty. This article describes how to use
ViewState to recreate and reinsert the postback values into the objects to
access their values.

Background

An ASP.NET application with pages that use dynamic generation of controls that
need to retain state across postbacks. The solution described in this paper
enables you to create a totally dynamic number of controls at runtime and
retreive their values after postback.

Solution

Dynamically added controls have no object reference variable in the codebehind
class. They appear only in the control collection of the containing control,
i.e. the Page.Controls collection. When the page is posted back to the server
as a result of user interaction a new instance of the codebehind class is
instantiated, and all the variables of the class is set with values from the
ViewState.

This means that the objects we are accessing from the codebehind class, that
"feels" like the same objects as we worked on before postback, actually are new
ones that got their predecessors values via ViewState and ASP.NET state
management.

So, the controls that were dynamically created are no longer there and
consequently the values returned from these controls have no place to go. They
are lost in the viewstate.

In order to catch these values the dynamically generated controls needs to
be re-generated at Page_Load. The important thing is to assign the
same ID to each control. The ViewState uses the ID property of the Control
objects to reinstate the values.

Note that the createControls method has to simulate the way that
you dynamically built your page before the postback. The important thing here
is obviously to assign identical ID values to the correct type of controls to
that we can access them at postback.

Points of Interest

This solution works because the
ASP.NET ViewState supports dynamically added controls, but does not do the
re-generation for us. As long as the ID properties match ASP.NET does the rest
of the job for us.

Thanks to Eric Sütter for
providing valuable input on this article!

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

There is one solution for which the child controls do not have to be re-created. I came across an article in which the author builds up a control called "DynamicControlsPlaceholder". This control is derived from PlaceHolder class but has built to enable saving its child-controls for subsequent postbacks. It's a great control. You can refer to it at:

You should always add your dynamic controls on the PreInit event (or Init, if you're using a MasterPage). You'd lose asp.net theming functionalities otherwise, unless you explicitly call .ApplyStyleSheetSkin() on each added control.

Also, it must be noted that a dynamically added control state cannot be retained at all: try changing the visibility or width of those controls and it won't be retained. That's because it's not the ViewState who's responsible for retaining each control value, try decoding the viewstate value to see no reference to those controls. You could disable it altogether and this example would still work. In reality, it's Asp.net that's doing something else other than parsing and validating a viewstate when a postback occurs. Asp.net enumerates the controls in a page and if any of them implements IPostBackDataHandler, it will call their LoadPostData method passing the Request.Form collection and a collection Key as parameters. The control will then figure out how to set its own value (its Text property if it's a textbox, Checked if it's a checkbox and so on).

So, Labels values are not retained because the Label class doesn't implement IPostBackDataHandler. This is understandable, a Label it's not rendered as a form control.

hi, and thanks for this useful post.
i have one gridview in my asp.net 2.0 page and i fill it by table dynamically at runtime. i inserted check boxes at the last column to select by user for deleting or editing. but when i press button and page is posted back , selected check boxes have been lost(with their values)...!!
let me to know how can i solve this problem.

I've been trying for almost 3 days to discover the problem why I cant get the control values after post back.

Here is my code please help me.

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

In default.aspx.cs
------------------------------------------------------------------------------------------------
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Web.Mail;
using System.Web.Security;
using System.Globalization;
using System.Security.Cryptography;
using System.Text;

Everytime you click the image button,a postback occurs.This implies that,the page is going to be loaded once again.
Since,you are creating checkbox on every page load,the checkboxes you checked dies on occurrence of postback event ie.on being posted to server and you end up seeing new checkboxes each time WHICH WERE NEVER CHECKED ANYWAY.
So,you need VIEWSTATE to persist the values among postbacks.

Solution:

*Execute the code you have written in the page_load only once ie.during the first time the page is requested.

*Before you click the image button,save the state of the page in viewstate so that it can be retrieved during subsequent page loads.

I agree with you and i guess it would be a new property e.g. Textvalue that would be assigned to the viewstate but, i wonder if you can just drop few lines how it really should look like. I am confused about adding the new label's text value to the viewstate.
Thanks

hi,
i have a dynamically created survey page using the placeholder control.Once the user creates their survey i want it to be saved to a mysql database when they click the submit button.
im trying to loop thru the placeholder control and use findcontrol to find the actual text value of the placeholder so it can then be stored in a database.
it doesnt seem to be working but im not too sure how to use the findcontrol method anyway and theres no reference to it in any of the .net books i have
heres the snippet of code:

i was also wondering ive read articles about problems with dynamic controls being lost after postback..if im saving to database this wont affect me will it,cos the articles were a little too complex for me to understand fully

when you add a label danamically into a page (using some script) you don't actually add a label you just add a <span></span> tag that contains the text and this is not parsed into a label when posted back