ViewState Tracking in ASP.NET Controls

Let’s say you have the following snippet of code below. The code
dynamically
instantiates a new ASP.NET control, changes the title property and then
adds the control to the control collection of a placeholder on the
page – a typical approach to dynamically creating controls.  When
the control loads, it adds an item into the drop down list
items collection with the same name as the current title property
value.  The title property of the control stores it’s value in the
ViewState, so that the title value is retained between page post
backs.  The problem is, this code does not work as expected. After
a post back the value of the title property is lost – why?

using System;
using System.Web.UI.WebControls;
using System.Collections.Generic;

public class MyDropDownList : DropDownList
{
public string Title
{
get { return ViewState[“myTitle”] as string; }
set { ViewState[“myTitle”] = value; }
}

protected override void OnLoad(EventArgs e)
{
this.Items.Clear();
this.Items.Add(new ListItem(Title));
}
}

public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
MyDropDownList ctrl = new MyDropDownList();
ctrl.Title = “Hello World!”;
myPlaceHolder.Controls.Add(ctrl);
}
else
{
MyDropDownList ctrl = new MyDropDownList();
// No need to assign title as it should be in the viewstate – right?
myPlaceHolder.Controls.Add(ctrl);
}
}
}

Finding the answer to this problem took some digging buy a co-worker –
The problem occurs because the control is not tracked by the ViewState
until the control is added to the parent container’s control
collection. Once the control is added to the control collection of the
placeholder, ViewState tracking is turned on and changes to the title
property are then stored in the ViewState.  In the above example, the
title of the control was assigned before the control was added to the
placeholder control collection, so the ViewState had not tracked a
change to the title, and therefore did not persist the value.

When dynamically creating user or server controls in ASP.NET always add
the control to the container controls collection before manipulating
the ViewState
.

The code below fixes the problem:

using System;
using System.Web.UI.WebControls;
using System.Collections.Generic;

public class MyDropDownList : DropDownList
{
public string Title
{
get { return ViewState[“myTitle”] as string; }
set { ViewState[“myTitle”] = value; }
}

protected override void OnLoad(EventArgs e)
{
this.Items.Clear();
this.Items.Add(new ListItem(Title));
}
}

public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
MyDropDownList ctrl = new MyDropDownList();
// Add the control to the placeholder controls collection to enable ViewState tracking.
myPlaceHolder.Controls.Add(ctrl);
ctrl.Title = “Hello World!”;
}
else
{
MyDropDownList ctrl = new MyDropDownList();
myPlaceHolder.Controls.Add(ctrl);
}
}
}