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.
- 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;
- 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.
- 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.
- 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.