Managing State Within Server Controls

With the introduction of ASP.NET 2.0, there are now two kinds of state management at the disposal of control developers: view state and control state. ASP.NET 2.0 makes a distinction between page-wide view state and control state to allow developers to turn off view state for an entire page to speed up performance, and selectively allow individual controls to maintain their state.

View state is a feature of ASP.NET that allows controls and the page itself to maintain state between requests by storing that state information in a hidden form variable. The contents of that hidden form variable are exposed through an instance of the StateBag class as the ViewState object. You can read and write name-value pairs using the following syntax:

int selectedIndex = ViewState["selectedIndex"]; ViewState["selectedIndex"] = comboBox1.SelectedIndex; 

Although view state is an incredibly powerful tool and facilitates many things in ASP.NET that required a lot of tedious programming before ASP.NET was released, it can become a performance problem. For example, in ASP.NET 1.1, if a DataGrid was bound to several hundred rows of data, all of that data could end up in view state in order to avoid requerying the server. The nature of the view state hidden form variable led to incredibly large page sizes in this situation. Before ASP.NET 2.0, control builders either had to rely on view state or they had to use some other mechanism to maintain state between page requests.

The size of view state became a burden for controls that only needed to maintain small amounts of data between requests. With ASP.NET 2.0, control state can be used to maintain small pieces of information between requests, whereas view state is still useful for storing large amounts of data.

Control state management follows a different model than view state. Rather than accessing the name/value pairs stored in the ViewState object, any control that you build should override the LoadControlState(object) and SaveControlState() methods that are now part of the WebControl class.

The LoadControlState method is used to restore the control's state from the object supplied as a method parameter. SaveControlState is used to return the object that constitutes the control's state. These two methods combined allow the control to manage its own state without resorting to the ViewState object. Keep in mind that control state should only be used for small values and control state cannot be disabled. Even if the page or the control has had EnableViewState set to false, control state code will still work properly.

Listing 30.2 contains the source code for a custom server control named StateControl. It is a control that uses ViewState for storing a list of strings to which the control is bound and it uses ControlState for storing the currently selected index to highlight an individual string.

Listing 30.2. Custom Control Using View State and Control State

using System; using System.Drawing; using System.Security.Permissions; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.Util; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; namespace CustomControls { public class StateControl : CompositeControl { private List<string> stringList = null; private int selectedIndex = -1; private Table mainTable = null; public List<string> DataSource {     get     {         if (stringList == null)             stringList = (List<string>)ViewState["stringList"];         return stringList;     }     set     {         stringList = value;         ViewState["stringList"] = value;     } } public int SelectedIndex {     get { return selectedIndex; }     set { selectedIndex = value; } } public override void DataBind() {     base.DataBind();     EnsureChildControls();     for (int x = 0; x < DataSource.Count; x++)     {         TableRow tr = new TableRow();         if (selectedIndex == x)             tr.BackColor = Color.LightBlue;         else             tr.BackColor = Color.White;         TableCell td = new TableCell();         td.Text = DataSource[x];         tr.Cells.Add(td);         mainTable.Rows.Add(tr);     } } protected override void LoadControlState(object savedState) {     Page.Response.Write("LoadConstrolState: " + savedState.ToString()+"<br/>");     selectedIndex = (int)savedState; } protected override object SaveControlState() {     Page.Response.Write("SaveControlState: " + selectedIndex.ToString()+"<br/>");     return selectedIndex; } protected override void RenderContents(HtmlTextWriter writer) {     base.RenderContents(writer); } protected override void CreateChildControls() {     Page.RegisterRequiresControlState(this);     mainTable = new Table();     mainTable.Width = new Unit(100, UnitType.Percentage);     Controls.Add(mainTable); } } } 

The DataSource property makes use of the ViewState object to retrieve the data from view state if it wasn't set during the page load. This allows the control to maintain the list of strings between page requests without requiring the host page to set them every time. The LoadControlState and SaveControlState overridden methods load and store the value of selectedIndex, and the DataBind() method uses that value to selectively determine which row to highlight in light blue. Finally, the following line tells the page framework that this control takes part in control state persistence:


Without this line of code, ASP.NET will not restore the control's state. Listing 30.3 contains the code for the page that hosts this control.

Listing 30.3. A Page Hosting a State-Persisting Control

using System; using System.Data; using System.Configuration; using System.Collections; using System.Collections.Generic; 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; public partial class StateDemo : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { if (!Page.IsPostBack) {     List<string> stringList = new List<string>();     stringList.Add("String One");     stringList.Add("String Two");     stringList.Add("String Three");     StateControl1.DataSource = stringList;     StateControl1.SelectedIndex = 2; } StateControl1.DataBind(); } protected override void OnPreRender(EventArgs e) { base.OnPreRender(e); Response.Write("Requires control state: " +   RequiresControlState(StateControl1) + "<br/>"); } protected void button1_Click(object sender, EventArgs e) { Response.Write("Button was pressed, this is a post back.<br/>"); Response.Write("StateControl Selected Index: " +     StateControl1.SelectedIndex.ToString() +"<br/>"); } } 

This code illustrates how you can create custom server controls that take part in view state and control state.

Microsoft Visual C# 2005 Unleashed
Microsoft Visual C# 2005 Unleashed
ISBN: 0672327767
EAN: 2147483647
Year: 2004
Pages: 298 © 2008-2017.
If you may any questions please contact us: