Click here to Skip to main content
11,804,008 members (81,216 online)
Click here to Skip to main content

DataGrid101: Using Windows.Forms DataGrid

, 14 May 2003 CPOL 528.2K 2.7K 145
Rate this:
Please Sign up or sign in to vote.
Tutorial on the usage of Windows.Forms.DataGrid


Visual Studio .NET comes with an out-of-the-box grid control called DataGrid. Complete with data-binding and many nifty features, it seems like a handy control. However, once you start using it, you may find that its usage is somewhat cumbersome and - in many real-life situations - downright puzzling. This article attempts to lead the beginner through the ropes of using DataGrid, including:

  • Data binding complex DataSets and OO class hierarchies
  • Adjusting columns and various "style" issues
  • Building usable context menus which behave according to position
  • Refreshing data updated outside of the grid code

Test Case

DataGrid is extremely easy to use when addressing a single table. Its navigation abilities give a very sexy (although I tend to be a skeptic regarding usefulness) view of table relations. In order to avoid the obvious, I designed a simple yet realistic domain with structure and requirements that do not fit the simple binding abilities of DataGrid. I call this domain Cars and I will use it for examples throughout this article:

  • A Car has 3 attributes: licensePlate, carType and price
  • A CarType has 2 attributes: name and manufacturer
  • A Manufacturer has a name

This domain can be found in the attached ZIP in 3 forms:

  1. A Jet Database (Cars.mdb)
  2. An XML schema (ObjectCars\CarDataSet.xsd)
  3. A set of class files (ObjectCars\Car.vb,CarType.vb, CarManufacturer.vb)

The requirement is simple: write a grid-like screen to manage car prices. A snapshot was given above.

Data Binding

Why does DataGrid binding fall short? DataGrid defines its DataSource as a single IList, be it DataTable or object Array (multiple tables will create a "navigate" interface). While it is easy to infer all data relevant for a car by walking through relations/references, DataGrid column binding does not support a "dot" notation. In other words, when binding to a list of Cars, I can display Car.licensePlate, but not Let us walk through 3 possible solutions, each with its pros and cons.

Join Based DataBinding

When it comes to data querying, there is nothing easier or more maintainable than using SQL. A simple SQL join statement can feed the relevant data into a DataTable fashioned for our use. Pros: fast, easy, simple and maintainable. Don't stop reading here, because there are several flaws…

  1. While you easily got the data to display, updating is now a major hassle: you need to "break" back into the original table structure before you can update your data base
  2. In the 3-tier scenario there is something inherently wrong with requesting the server for data structured specifically for your screen. In cases where you don't own the server it is not only wrong, it is impossible.
  3. The inherent data redundancy typical to a join (the same data exists in many rows) is error-prone when it comes to row creation.

An example of this approach can be found in the attached ZIP: SingleQueryCars\SQLJoinBasedForm.vb.

Multiple Table Based DataBinding

Microsoft tutorials emphasize the DataSet ability to store complex table structures allowing higher client independence and fewer round trips. Once we embrace this philosophy, we are required to join the tables on the client side: no SQL. Unfortunately, .NET does not include a Joiner utility class, so we need to join data in our code. The procedure is quite simple:

  1. Define a new DataSet and, in it, a table with the required structure
  2. Fill it by looping on the child table, in our case Cars

Here is the code:

Dim carRec As DataRow
Dim viewRec As DataRow
For Each carRec In MyCarsDataSet.Tables("Cars").Rows
  viewRec = MyGridViewDataSet.Tables("CarView").NewRow
  viewRec("license") = carRec("license")
  viewRec("type") = carRec.GetParentRow("TypesCars"). _
  viewRec("make") = carRec.GetParentRow("TypesCars"). _

Essentially this is the same as what we did in an SQL join. The main benefit is client/server de-coupling, i.e. no server coding for grid purposes. The biggest drawbacks are client-side performance and additional procedural code. An example of this approach can be found in the attached ZIP: JoinBasedCars\LoopBasedJoinForm.vb.

Object List Data Binding

In many cases, it is best to leave DataSets as a link to the underlying DB and perform data manipulation using a class hierarchy (a.k.a. an "Object Domain"). The more logic in your application, the better this approach will serve you. Furthermore, in some cases Object Models are all we have. An example is when our server insists on handing data in Object form. Since "dot notation" is not supported, how can we display properties of anything but our "root objects" (i.e. cars)?

The solution is simple, although it may seem cumbersome at first: we create a new class (usually referred to as the "viewer" class), which wraps the root object and exports all needed data as properties. For instance, in our example we would code a CarViewer class wrapping a Car object and exporting the properties licensePlate, typeName and manufacturerName. We would then bind an ArrayList of these to the DataGrid.

It turns out that this solution is extremely powerful, since it gives us a natural place for a user-interface related code that is non-trivial: things like calculated attributes, complex use cases (how about "switch plates with another car"), etc. In fact, it usually makes sense to use viewer-based grids instead of performing "procedural joins," even if you have the data in a DataSet and not an Object Domain.

Not surprisingly, the author did not invent this concept. It is an adaptation of a well-known paradigm called MVC (Model-View-Controller) and you are welcome to read any of the multitudes of excellent articles available on the Internet. An example of this approach can be found in the attached ZIP: ObjectCars\ViewerBasedForm.vb.

Refreshing the Grid

No matter how you perform data binding, if your application views dynamic data you are bound to refresh the grid at some time. It turns out that this is another trivial task that was made "un-obvious." Here's how:

  1. Get the DataGrid CurrencyManager
  2. Call its refresh method

Note the parameter to BindingContext. This is where most people fail. It should be a reference to the exact object you bound.

' Get currency manager 
Dim cs As CurrencyManager = _
  CType(MyDataGrid.BindingContext(MyCarsDataSet.Cars), _
' Refresh

For all you c#/c++/j# types: CType is the VB.NET cast operator.

Formatting the Grid

Now that we have all relevant data bound, it's a good idea to make it human-readable. Grid formatting is relatively easy, but from the amount of discussion devoted to it in news groups, one can infer that Microsoft did not expose it very neatly. I will try to sort the basics and give some pointers to more advanced stuff.

Basic Column Formatting

All grid formatting is centered about the TableStyles collection accessible via the grid property window. Here is how it works:

  1. A style defines most of the grid formatting properties, including column format (via a collection called GridColumnStyles)
  2. At any given moment, the grid adheres to one style selected according to the style MappingName property

Once you understand this, many of the basic tasks are, well, basic. Here are some examples:

  • Column caption, width, Read/Write, control type (text box / check box) and more are defined in the column style
  • Column order is determined by GridColumnStyle order
  • If we want to "hide" a column, we don't map it to any column style

The only trick left is to determine the right mapping name:

  • When grid shows a DataSet DataTable, use the table name as defined in the schema
  • When grid shows an object data structure, use the structure data type (i.e. ArrayList)

Examples for this can be found in all 3 forms supplied in the attached ZIP. Of course, all these properties are accessible at runtime, allowing easy implementation of features such as "re-arrange columns," "hide column," etc.

Advanced Formatting

Unfortunately, some extremely useful features we expect of a DataGrid are not easily implemented and require more advanced programming. Chief among these are:

  • The ability to use controls other than text box and check box
  • The ability to dynamically control colors and fonts at cell level

Once we understand that the heart of formatting is the DataGridColumn class, then it is evident that to achieve advanced formatting we need to extend it in a manner that fits us. Excellent pointers for such work can be found here (combo in grid).

Context Menus

In real life applications, grids will usually have more than one context menu: column header menu will differ from cell menu; row header menu might differ from both and sometimes the menu may be affected by selection areas. Although DataGrid has only one ContextMenu, managing this kind of behavior is simple enough:

  1. Create all needed menus, either on the designer or dynamically
  2. Write a handler for the DataGrid.MouseDown event:
    1. Check for right-click
    2. Compute the row/column clicked
    3. Set the DataGrid.ContextMenu according to context

Note that this works since your handler is called before the context menu is displayed. Here is an example that shows a context menu only when clicked over a cell. It stores cell coordinates for later use by the context menu handlers:

Private Sub MyDataGrid_MouseDown(ByVal sender As Object, _
    ByVal e As System.Windows.Forms.MouseEventArgs) _
    Handles MyDataGrid.MouseDown
  Dim hi As System.Windows.Forms.DataGrid.HitTestInfo
  hi = MyDataGrid.HitTest(e.X, e.Y)

  ' Test if the clicked area was a cell.
  If hi.Type = DataGrid.HitTestType.Cell Then
     Me.MyDataGrid.ContextMenu = Me.GridContextMenu
     Me.manipulatedRow = hi.Row
     Me.manipulatedColumn = hi.Column
     ' of course I could have saved the whole "hi" structure.
    Me.MyDataGrid.ContextMenu = Nothing
  End If
End Sub

The Attached Source Code

That's it, folks. The attached ZIP contains 3 projects:

  1. SingleQueryCars is a read-only grid based on an SQL join; it mainly shows column customization.
  2. JoinBasedCars has similar functionality, but it also exemplifies client side join of several DataSet tables
  3. ObjectCars is a bit more interesting (as I believe this is the best way most of the time); it demonstrates all discussed and a bit more, including:
    • Simple mapping a data set to an object domain
    • Viewer management
    • Column formatting
    • Context menu usage
    • Adding lines, deleting lines, hiding lines


There are already several .NET grids on the market which look much better than DataGrid and more will come. However, when used correctly, DataGrid can still take you a long way to a usable user interface and it is certainly worth your while experimenting with it further.


  • 15 May, 2003 -- Original version posted
  • 11 September, 2003 -- Updated


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Web Developer
Israel Israel
Omri started coding way back in the good ol' Apple ][ days. His first commercial (acutally governmental) software package was released 1986.
In the 90's Omri programmed C and C++, and managed larger development teams using MFC/COM.
In the last 3 years he is into Java server programming, and while he loves the language and community, he has many reservations. Maybe this is why .Net feels like comming back home...

You may also be interested in...

Comments and Discussions

Generalhow to remove blue bar are appearing from switching of one childform into anather in mdiform using Pin
jayawant sawant10-May-11 18:58
memberjayawant sawant10-May-11 18:58 
Generaldtagrid problem in Pin
Amran hossain30-Apr-09 3:59
memberAmran hossain30-Apr-09 3:59 
Generalpopulating datagrid from sql database Pin
Jeffrey Mukala3-Nov-08 20:09
memberJeffrey Mukala3-Nov-08 20:09 
QuestionHello, can someone advice me how to add a column with links to PDF to a GridView ??? Pin
Gazit Eran10-Feb-08 2:22
memberGazit Eran10-Feb-08 2:22 
QuestionHello, can someone advice me how to add a column with links to PDF to a GridView ??? Pin
Gazit Eran10-Feb-08 2:14
memberGazit Eran10-Feb-08 2:14 
QuestionDatagrid Export to Text File ? Pin
KostasKir28-Aug-07 21:36
memberKostasKir28-Aug-07 21:36 
QuestionPlz help me Pin
donekjose21-Jun-07 18:57
memberdonekjose21-Jun-07 18:57 
Generali have doubt in datagrid Pin
J512198226-Mar-07 20:13
memberJ512198226-Mar-07 20:13 
GeneralDataGrid101 - Using Windows.Forms DataGrid Pin
Neill Rutherford13-Feb-07 22:37
memberNeill Rutherford13-Feb-07 22:37 
Questionhelp!!! Pin
wazb18-Jan-07 20:36
memberwazb18-Jan-07 20:36 
GeneralUpdate Calc'd Field on Data Change Pin
TulsaPilot26-Oct-06 8:18
memberTulsaPilot26-Oct-06 8:18 
Questionhow to update data from datagrid to database Pin
jashj18-Aug-06 20:41
memberjashj18-Aug-06 20:41 
GeneralPlease Help me proceed with my project........ very Urgent.. Pin
Naveen pal12-Jan-06 23:04
memberNaveen pal12-Jan-06 23:04 
GeneralTableStyle from a Collection object (no datatable) Pin
jfeil26-Dec-05 5:25
memberjfeil26-Dec-05 5:25 
GeneralRegarding with Data Grid Pin
SanjuVargheseJohn7-Dec-05 23:35
memberSanjuVargheseJohn7-Dec-05 23:35 
GeneralGrid not showing data until... Pin
Anonymous12-Oct-05 3:56
sussAnonymous12-Oct-05 3:56 
GeneralStructure To a Datagrid Pin
itssuk11-Oct-05 22:21
memberitssuk11-Oct-05 22:21 
GeneralDataGrid Refresh Problem Pin
Morfoman21-Sep-05 22:57
memberMorfoman21-Sep-05 22:57 
GeneralRe: DataGrid Refresh Problem Pin
jeyjobs11-Jul-06 2:14
memberjeyjobs11-Jul-06 2:14 
GeneralRe: DataGrid Refresh Problem Pin
ravishing_raza21-Jan-07 7:32
memberravishing_raza21-Jan-07 7:32 
GeneralDatagrid context menu Pin
Anonymous23-Aug-05 0:13
sussAnonymous23-Aug-05 0:13 
Generaldatagrid Pin
mutahar21@hotmail.com19-Aug-05 7:05
membermutahar21@hotmail.com19-Aug-05 7:05 
Generalrid Pin
mutahar21@hotmail.com19-Aug-05 5:23
membermutahar21@hotmail.com19-Aug-05 5:23 
GeneralValidating cell before updating Pin
Michiel Rotteveel22-Jul-05 11:27
memberMichiel Rotteveel22-Jul-05 11:27 
GeneralViewer Arraylist Pin
windcloud0315-Jun-05 23:26
memberwindcloud0315-Jun-05 23:26 
GeneralData Grid Formating Pin
tmcalvin0425-May-05 16:25
membertmcalvin0425-May-05 16:25 
QuestionHow do I prevent from user to add more rows to datagrid Pin
newmans.five21-May-05 10:00
membernewmans.five21-May-05 10:00 
Excellent example of data grids, it helped me a great deal.. I have a few questions I hope that you can help me with.

1. How can you prevent a user from adding additional rows?
2. I want to populate a table with 10 rows. I want them to be able to type/edit directly in the rows. I do not want them to be able to add any more rows.

AnswerRe: How do I prevent from user to add more rows to datagrid Pin
_SlowArrow_22-May-05 22:54
member_SlowArrow_22-May-05 22:54 
AnswerRe: How do I prevent from user to add more rows to datagrid Pin
Anonymous4-Jun-05 3:51
sussAnonymous4-Jun-05 3:51 
GeneralRe: How do I prevent from user to add more rows to datagrid Pin
cupycake_jay5-Jan-06 5:35
membercupycake_jay5-Jan-06 5:35 
GeneralSome questions to the sample program Pin
_SlowArrow_17-May-05 23:10
member_SlowArrow_17-May-05 23:10 
GeneralRe: Some questions to the sample program Pin
_SlowArrow_18-May-05 0:17
member_SlowArrow_18-May-05 0:17 
GeneralRe: Some questions to the sample program Pin
_SlowArrow_18-May-05 1:59
member_SlowArrow_18-May-05 1:59 
QuestionHow to catch the server? Pin
Eteleeb7-Apr-05 11:37
memberEteleeb7-Apr-05 11:37 
AnswerRe: How to catch the server? Pin
BigGreenCleanMachine23-Jun-05 10:22
memberBigGreenCleanMachine23-Jun-05 10:22 
GeneralUpdating Directly From the DataGrid Pin
satcomengineer13-Mar-05 7:39
membersatcomengineer13-Mar-05 7:39 
GeneralProblems with writing dates Pin
karoumbr30-Dec-04 22:13
memberkaroumbr30-Dec-04 22:13 
Generalsingle row selection in a datagrid Pin
André Voigt25-Oct-04 0:20
memberAndré Voigt25-Oct-04 0:20 
GeneralServer.Transfer in Datagrid Pin
varn@austin.rr.com30-Sep-04 2:32
membervarn@austin.rr.com30-Sep-04 2:32 
GeneralRe: Server.Transfer in Datagrid Pin
Anonymous13-Sep-05 9:16
sussAnonymous13-Sep-05 9:16 
GeneralLoad DataGrid from code Pin
plestrel2-Aug-04 15:57
memberplestrel2-Aug-04 15:57 
GeneralRe: Load DataGrid from code Pin
PrasadGVL11-Oct-04 18:50
memberPrasadGVL11-Oct-04 18:50 
GeneralDataGrid cell background color Pin
Al Alberto24-Jul-04 13:12
memberAl Alberto24-Jul-04 13:12 
GeneralDeleting Records Pin
Mike Stanfield29-Jun-04 7:08
memberMike Stanfield29-Jun-04 7:08 
GeneralHide column and get visibly data Pin
GladaFrasse26-Apr-04 21:48
memberGladaFrasse26-Apr-04 21:48 
GeneralDatagrid XML Binding Boolean Pin
BalooElland3-Feb-04 3:41
sussBalooElland3-Feb-04 3:41 
QuestionHow to make Form.DataGrid caption Clickable. Pin
Neeraj Jain10-Nov-03 8:10
memberNeeraj Jain10-Nov-03 8:10 
GeneralProblems with Databinding, with nested objects properties Pin
mdan2-Nov-03 20:14
membermdan2-Nov-03 20:14 
GeneralSorting Tables.. Pin
Hydra25-Oct-03 13:47
memberHydra25-Oct-03 13:47 
GeneralSort in datagrid with datasource ArrayList Pin
pepe1234566-Sep-03 1:41
memberpepe1234566-Sep-03 1:41 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.151002.1 | Last Updated 15 May 2003
Article Copyright 2003 by omri
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid