Storing a List<> of Objects in ViewState

Basically what I initially wanted to do was create a GridView in ASP.NET and add items to the Items collection programmatically. This isn’t possible though, GridView doesn’t have an items collection because it’s a DataBoundControl and not a ListControl like f.e. a ListBox, RadioButtonList, CheckBoxLIst etc.

I couldn’t just go and create a temp database where I would insert the data and bind this table to the GridView.

The scenario what I have is the following. The user sees a page, enters some data in a couple textboxes and has the ability to add records that are linked to the the info in the textboxes. I want to process everything when everything is filled in. I know it’s not common but anyway..I couldn’t come up with an idea at first so I did some thinking. I had to have something that would store these records, bind them to the GridView and stay there after PostBacks to the server (Adding of new record f.e.) occur. Ok so State Management popped in my mind. I wanted to make use of the ViewState, you can store info there within the bounds of a single page.

A simple example of ViewState is the following:

//Set Value in ViewState ViewState["Blog"] = "MsHelp"; //Get Value from ViewState if (ViewState["Blog"] != null) { Response.Write(string.Format("My blog is called, {0}", ViewState["Blog"])); }

If you wouldn’t check the ViewState for a null value and it would for some reason be null, a NullReferencePointer Exception would be thrown.

Now, except for storing strings, ints or any other primitive type, you can also store objects in the ViewState. This is done as follows:

//Customer Class [Serializable] public class Customer { public string CustName { get; set; } public string CustAddress {get;set; } } //ASP.NET Code Behind file //Create Customer object Customer cust = new Customer(); cust.CustName = "Sven"; cust.CustAddress = "Vlinderlaan 99"; //Set Customer object in ViewState ViewState["CurrentCustomer"] = cust; //Get Value from ViewState if (ViewState["CurrentCustomer"] != null) { //Create a new Customer object Customer OldCustomer; //Cast ViewState Object to Customer Object OldCustomer = (Customer)ViewState["CurrentCustomer"]; Response.Write(string.Format("Hello, {0}. You seem to be living on the {1}",OldCustomer.CustName,OldCustomer.CustAddress)); }

 

Mind the [Serializable] attribute in front of the Customer Class. This is needed the object has to be converted to a stream of bytes so it can be added to a hidden field on the page, this is done using Serialization. If this attribute wouldn’t be supplied you would end up with a System.Runtime.Serialization.SerializationException.

We’re almost there, but the problem here is, I don’t want to store a single object in ViewState. I want to store several objects and bind these to a GridView so the user has a nice list with columns and can see what kind of records he/she added. Ok let’s at this final step. Like I said, we’re almost there.

Ok so let’s first take a look at the asp.net page. I need a GridView and some textboxes to add a customer with a name and address. I added 2 boundFields to the GridView with CustName and CustAddress as DataField.

<div> <table> <tr> <td> <asp:GridView ID="gvCustomers" runat="server" AutoGenerateColumns="False" EmptyDataText="No customers added!"> <Columns> <asp:BoundField DataField="CustName" HeaderText="Name" /> <asp:BoundField DataField="CustAddress" HeaderText="Address" /> </Columns> </asp:GridView> </td> <td style="vertical-align: top;"> <table> <tr> <td> Name: </td> <td> <asp:TextBox ID="txtName" runat="server"></asp:TextBox> </td> </tr> <tr> <td> Address: </td> <td> <asp:TextBox ID="txtAddress" runat="server"></asp:TextBox> </td> </tr> <tr> <td> <asp:Button ID="btnAdd" runat="server" Text="Add Customer" OnClick="btnAdd_Click" /> </td> </tr> </table> </td> </tr> </table> </div>

Now let’s look at the code behind of this page.

protected void Page_Load(object sender, EventArgs e) { BindCustomers(); } private void BindCustomers() { if (ViewState["Customers"] != null) { gvCustomers.DataSource = (List<Customer>)ViewState["Customers"]; gvCustomers.DataBind(); } else { List<Customer> customers = new List<Customer>(); ViewState["Customers"] = customers; } } protected void btnAdd_Click(object sender, EventArgs e) { if (!string.IsNullOrEmpty(txtName.Text) && !string.IsNullOrEmpty(txtAddress.Text)) { Customer cust = new Customer(txtName.Text.Trim(), txtAddress.Text.Trim()); ((List<Customer>)ViewState["Customers"]).Add(cust); BindCustomers(); txtName.Text = string.Empty; txtAddress.Text = string.Empty; } }

As you can see in the Page_Load event I call the method BindCustomers. This checks if the ViewState is not null, if it isn’t bind it to the GridView. You see that I first cast the ViewState to List<Customer>. This indicates that it’s a list of Customer Objects. If the ViewState is null, let’s create a new list and add it to the ViewState.

In the Button Click event I check if the Textboxes aren’t null of empty. If they aren’t I create a new Customer Object (I added a constructor to the Customer Class). Then I cast my ViewState to the List<Customer>. This is done between brackets. Now the intellisense has all the List operations and knows the CLR it’s a List. Then I add the Customer object to the list using the Add() method. Now another Customer object is added to the ViewState. I bind again and clear the Textboxes. For people that haven’t worked with List<>, don’t forget to reference System.Collections.Generic; otherwise List<> will not be recognised.

image

Some people may think this is a very uncommon scenario. I just was in this situation and I wanted to make it work, this is how I did it and it worked.


No comments yet. Be the first.

Leave a reply

*
To prove you're a person (not a spam script), type the security word shown in the picture. Click on the picture to hear an audio file of the word.
Click to hear an audio file of the anti-spam word