Saturday, August 11, 2012

DataGrid and Object Binding

Last week, one of my good friends asked me some questions about using DataGrid in Windows Form app. I looked at his codes. My first reaction, after I saw his codes, was to recommend him using object or class as data source binding instead of SQL or LINQ binding. I have experience using ASP.Net DataGrid with object binding in my previous work proejcts. I like this strategy very much. By using class as data source, as a developer, I have total control of how data being pumped into DataGrid. The comlicated SQL data structure should be left at SQL server side. The .Net project should forcuse on data and UI.

I quickedly showed him an example. First I added an example class MyData as a data object template. Then I added a DataGrid control on a Windows form. I used data source wizard from the form's DataGrid to set up its object data source to MyData. That was very quick and easy, based on my ASP.Net experience. However, the wizard does not provide a way to let me to tell which method the DataGrid to get data. It seems that DataGrid for Window Form is very different from the one for ASP.Net.

After that meeting, one day, I created an example project and tried to figure it out. Now I got the solution. Basically, in the case of Windows Form application, the data source for DataGrid should a be collection, not an object class. It is very different from the case of ASP.Net DataGrid. Since the data source is a collection, the data binding to DataGrid has to be manually added from DataGrid UI wizard. That's very easy to do: adding column header text and data binding property of DataPropertyName.

Here is the simple Windows Form application. I added a DataGrid to Form1.

DataGrid has a designer wizard. Leave the Data Source as default (none). Click on Add Column... to  define data grid columns. For this demo, add two columns: Name and Age, with column header names as: Column Name, Column Age.

In order to bind data to DataGrid, I need to edit columns from Edit Columns... in DataGrid designer. From there, change DataPropertyName to Name and Age.

With above DataGrid settings, I add a simple class of MyData, which will be used as objects to be displayed on the DataGrid with only two properties: Name and Age. I added another static method to return a collection of MyData objects. Here are my simplified codes:

Public Class MyData
 Private m_name As String
 Private m_age As Integer

 Public Sub New(ByVal nameValue As String, _
     ByVal ageValue As Integer)
   m_name = nameValue
   m_age = ageValue
 End Sub

 Public Property Name() As String
     Return m_name
   End Get
   Set (ByVal value As String)
     m_name = value
   End Set
 End Property

 Public Property Age() As Integer
     Return m_age
   End Get
   Set (ByVal value As Integer)
     m_age = value
   End Set
 End Property

 Public Shared Function GetObjects() As List(Of MyData)
  Dim list As List(Of MyData)
  list = New List(Of MyData)
  list.Add(New MyData("John", 12))
  list.Add(New MyData("Mike", 21))
  Return list
 End Function
End Class

In reality, this method (GetObjects) should contain codes to get data from database, or to call data bridge to get mapped data from database.

For the Form, the codes are very simple:

Public Class Form1
 Private Sub Button1_Click(ByVal sender As System.Object, _
   ByVal e As System.EventArgs) Handles Button1.Click
   Me.DataGridView1.DataSource = MyData.GetObjects()
 End Sub
End Class

The basic concept of this strategy is to make the app as simple as possible: only two element in the Windows Form application:

  • a Form with DataGrid as UI; and 
  • MyData as data source template.

In this way, the focuse can be placed on UI, to provide convenient and nice format for client. The data bridge part, which provides data, can be placed in another class, library, or SQL server.

Here is the result of the application: