CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Peter's Gekko

public Blog MyNotepad : Imho { }

Using the viewstate in a control whose viewstate is disabled (you need a page base class)

The Datagrid is a lovely control when you need a web page whose layout has to adapt to a a huge variety of browsers. Just set the width of the grid to 100% and the grid's layout will scale quite well. When it comes to the page (response) size the datagrid is not that nice. The grid's viewstate will swallow a lot of bandwidth. In my case the size of a page with a grid went from 50k to 150k by just setting the grid's EnableviewSate property to true (which is the default). Most of the information in that viewstate is not needed at all. The data in the grid is dynamic, it is reread from a database on every roundtrip.

By switching off the grid's viewstate you do lose a little more than intended. A lot of events no longer fire. OnBubbleEvent (which fires when a control in a template has posted back), OnItemCommand (which fires when a linkbutton in the grid has posted back) and the specific command events like SelectCommand, SortCommand and the events dependending on these, like SelectedIndexChanged, no longer fire (on my .net server, some people report different). Using a little hack you can alwyas find out what kind of event posted back.

Some properties in the viewstate are hard to live without. To select an individual row you do need SelectedIndex. In ASP.NET 2.0 the essential properties have moved from the viewstate to the controlstate, in 1.x you have to do your own bookkeeping. The SelectedIndex cannot be preserved over roundtrips in the grids's viewstate but it can be stored in the viewstate of the page which owns the grid.

Storing and retreiving something in the viewsate is pretty easy:

const string myViewStateItemName = "_myViewStateItemName";
protected int myViewStateItem
{
   get
   {
      object o = this.ViewState[myViewStateItemName];
      if (o == null)
         return -1;
      else
         return (int) o;
   }
   set
   {
      this.ViewState[myViewStateItemName] = value;
   }
}

The viewstate is a name- value collection, the items are identified by a string. To make shure I use the same name when setting and getting the item that name is a constant. All values are stored as an object, it takes some casting to get the right type and some default value when the items wasn’t found (yet). Now the page has an integer property myViewStateItem.

Page is a property of a web-control, the grid can reach the page from code. I have created a custom datagrid which inherits from the DataGrid. A first attempt to store the selectedindex might look like this:

public class IndatoDataGrid : System.Web.UI.WebControls.DataGrid
{
  const string myViewStateItemName = "_myViewStateItemName";
   public
override int SelectedIndex
   {
   get
   {

      object o = this.Page.ViewState[myViewStateItemName];
      if (o == null)
         return -1;
      else
         return (int) o;

   }
   set
   {
      this.Page.ViewState[myViewStateItemName] = value;
   }
}

There are two things wrong with that

  • The ViewState property has a proptected visibility and is not available here
  • When two of these grids co-exist on one page they will both store their property in the same viewstate member

This is where the page base class comes in. You do not need a visual page, just add a class to your project which inherits from System.Web.UI.Page.

public class BasePage : System.Web.UI.Page
{
   public int GetViewStateInt(string name)
   {
      object o = this.ViewState[name];
      if (o == null)
         return -1;
      else
         return (int) o;
   }

   public void SetViewStateInt(string name, int value)
   {
      this.ViewState[name] = value;
   }

}

The class exposes two methods which store and reterieve an integer value to and from the page’s viewstate. Any webform can inherit from this class.

///
///
Summary description for StudieOnderdeel.
///
 
// <Update> this code has been slightly updated since the original </update>

public class StudieOnderdeel : BaseWebForm
{
   protected System.Web.UI.WebControls.Panel Panel1;
   // Etcetera 

Generating an unique name for the value is done in the code of the grid

public class IndatoDataGrid : System.Web.UI.WebControls.DataGrid
{
   private int GetInt(string name)
   {
      BasePage bp = this.Page as BasePage;
      if (bp != null)
          return bp.GetViewStateInt(VSname(name));
      else
         return -1;
   }

   private void SetInt(string name, int value)
   {
      BasePage bp = this.Page as BasePage;
      if (bp != null)
         bp.SetViewStateInt(VSname(name), value);
   }

   private string VSname(string varName)
   {
      return string.Format("{0}{1}", this.ID, varName);
   }

   const string myViewStateItemName = "_mySelectedIndexame";
   public override int SelectedIndex
   {
   get
   {
      return GetInt(VSname(myViewStateItemName));
   }
   set
   {
      SetInt(
VSname(myViewStateItemName), value);
   }
}

The grid has two methods, GetInt and SetInt. These cast the grid’s Page to a BasePage and use the BasePage’s methods to get the value in and out of the viewstate. The name of the viewstate member is composed by the VSname method, which combines the ID of the grid itself with the name passed. The combination will be unique on the page. The overridden SelectedIndex property uses these to preserve the selectedindex over roundtrips.

Now I have a datagrid which does preserve its SelectedIndex over roundtrips without a dramatic increase of viewstate size. 


Published Mar 23 2005, 04:14 AM by pvanooijen
Filed under:

Comments

Peter's Gekko said:

When it comes to building web applications ASP.NET 2.0 will make life a lot easier. The key to success...
# April 19, 2005 3:21 AM

Peter's Gekko said:

VS 2003, VS 2005, the datagrid and controlstate
I have built a lot of web application with Visual Studio...
# August 3, 2005 3:16 PM

Peter's Gekko said:

VS 2003, VS 2005, the datagrid and controlstate
I have built a lot of web application with Visual Studio...
# August 3, 2005 3:25 PM

Peter's Gekko said:

VS 2003, VS 2005, the datagrid and controlstate
The DataGrid with Visual Studio 2003 is a very nice...
# August 15, 2005 10:43 AM

Peter's Gekko said:

Author: &lt;a href=&quot;/blogs/peter.van.ooijen&quot;&gt;Peter Van Ooijen&lt;/a&gt;&lt;br /&gt;
The DataGrid with Visual Studio 2003 is a very nice control, however, when it comes to the viewstate and &quot;pushing your app through the wire&quot; it does have some serious drawbacks. Visual Studio 2005 does go a long way towards fixing these issues, but a better general approach to optimizing DataGrid performance is fighting viewstate size.
# August 22, 2005 11:16 AM

Peter's Gekko said:

Author: &lt;a href=&quot;/blogs/peter.van.ooijen&quot;&gt;Peter Van Ooijen&lt;/a&gt;&lt;br /&gt;
The DataGrid with Visual Studio 2003 is a very nice control, however, when it comes to the viewstate and &quot;pushing your app through the wire&quot; it does have some serious drawbacks. Visual Studio 2005 does go a long way towards fixing these issues, but a better general approach to optimizing DataGrid performance is fighting viewstate size.
# August 22, 2005 11:16 AM

Leave a Comment

(required)  
(optional)
(required)  

Enter the numbers above:
Add
Check out Devlicio.us!