Bind a Collection to a GridView

August 8, 2008 10:41 by wjchristenson2

Over the past few months I've had some requests to show how you can bind a custom object collection to a GridView.  When looking deeper into the collections, I noticed that the developers were working way to hard to create their collection class.   The collections were inheriting from System.Collections.Specialized.NameObjectCollectionBase and implementing IEnumerator, IEnumerable, & IUpdatable, etc to accomplish some simple tasks (ie: add, remove, for each loops, etc).  When implementing these interfaces, the developers were manually having to wire everything in.  On top of this, they were having problems binding to .NET controls.  Another quick point to make here is that the specialized collection does type casting at run time.

What I proposed was to inherit from System.Collections.Generic.List instead.  What this does is allow them to do their basic add, remove, sort, and manipulate their lists.  It also is strongly typed and can be accessed by index.  Generics provide better type safety and performance than non-generic collections (ie NameObjectCollectionBase mentioned above).

I'm going to create a simple vehicle collection and bind a GridView to it using the Generic.List.


   1:  Public Class Vehicle
   2:      Private _Make As String = String.Empty
   3:      Private _Model As String = String.Empty
   4:   
   5:      Public Property Make() As String
   6:          Get
   7:              Return _Make
   8:          End Get
   9:          Set(ByVal value As String)
  10:              _Make = value
  11:          End Set
  12:      End Property
  13:   
  14:      Public Property Model() As String
  15:          Get
  16:              Return _Model
  17:          End Get
  18:          Set(ByVal value As String)
  19:              _Model = value
  20:          End Set
  21:      End Property
  22:   
  23:      Public Sub New()
  24:   
  25:      End Sub
  26:   
  27:      Public Sub New(ByVal make As String, ByVal model As String)
  28:          _Make = make
  29:          _Model = model
  30:      End Sub
  31:  End Class

Here is the vehicle class (object) that we'll reference in our collection.  Now for the collection.


   1:  Imports System.Collections.Generic
   2:   
   3:  Public Class Vehicles
   4:      Inherits List(Of Vehicle)
   5:   
   6:  #Region "Constructors"
   7:      Public Sub New()
   8:          MyBase.New()
   9:      End Sub
  10:   
  11:      Public Sub New(ByVal capacity As Integer)
  12:          MyBase.New(capacity)
  13:      End Sub
  14:   
  15:      Public Sub New(ByVal collection As IEnumerable(Of Vehicle))
  16:          MyBase.New(collection)
  17:      End Sub
  18:  #End Region
  19:   
  20:  End Class

You'll notice how we inherit from System.Collections.Generic.List and cast the collection as a type of Vehicle.  It's as simple as that.  I added 3 constructors for your own reference.  Now all we have to do is add some data to the collection and bind a GridView to it.


   1:  Imports CollectionDataBinding.BLL
   2:   
   3:  Partial Public Class _Default
   4:      Inherits System.Web.UI.Page
   5:   
   6:      Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
   7:          If Not Page.IsPostBack() Then
   8:              GridView1_DataBind()
   9:          End If
  10:      End Sub
  11:   
  12:      Private Sub GridView1_DataBind()
  13:          Dim myVehicles As Vehicles = New Vehicles()
  14:          myVehicles.Add(New Vehicle("Ford", "Mustang"))
  15:          myVehicles.Add(New Vehicle("Pontiac", "Grand AM"))
  16:   
  17:          Me.GridView1.DataSource = myVehicles
  18:          Me.GridView1.DataBind()
  19:      End Sub
  20:  End Class

On page load, I bind the GridView if it is not a postback.  I create a new instance of the Vehicles collection and add 2 vehicles to it.  I then simply set the data source of the GridView to the Vehicle collection and call DataBind().  Now, each public property will be mapped and shown in your GridView if you have AutoGenerateColumns="true" set.  If you don't do this, you'd approach the custom column mappings the same way as with a DataTable, DataView, etc (TemplateField, Eval expressions).

CollectionDataBinding_Soln.zip (89.23 kb)

>>>>> Edit 8/21/2008 <<<<<

I found another article that relates to this post.  It's a great reference as to the benefits of using generic collections.  The article lists the following reasons why you should use generic collections.

  1. Readability and simplicity of your code. Let’s take the case of getting the first string in a list of strings. With generics you would declare List<T> myList = new List<T>(); and then say string firstString = myList[0] just like working with arrays. This syntax is much more simple and readable than what you used to have to write which was ArrayList myList = new ArrayList(); and then string firstString = myList[0] as string;
  2. Performance. Every time you add a value type to a non-generic collection you have to box it to make it an object and every time you retrieve a value type from a non-generic collection you have to unbox it back from object. Even with reference type you still need to cast back to the correct type when retrieving items.
  3. Working against new smaller Framework SKUs. In Silverlight we decided to remove all the concrete non-generic collections completely from the codebase. This is mostly because the Silverlight core managed libraries is set to be the smallest useful set of classes. It’s also possible that other future small frameworks will not have the non-generic collections in store. If you ever plan to write code for those frameworks — you should convert it to use the generic collections.
  4. Better type-safe libraries. If you are developing libraries to be consumed by 3rd parties you should most definitely use generic collections when possible. This would allow consumer of your libraries to quickly figure out what’s expected to be stored in the collections instead of having to guess or figure out from documentation.