Attention: We are retiring the ASP.NET Community Blogs. Learn more >

Getting to the source of the Windows.Forms.DataGrid

People that know me well know that - essentially - I'm a web guy. Gimme notepad, and a browser and I'm away. Anyways, in the past year or so I've stepped into more and more WinForms development (for many reasons) and, despite my elevation from WinForms wannabe to WinForms wiz I've continually been scared off by the DataGrid control... NOT ANY MORE!

A couple of days ago I IM'd RoyO about a problem I was having with the DataGrid and he directed me to this little gem:

Winforms Data Binding Lessons Learned

After reading that article I can now say - with total honesty - that the DataGrid holds no fears for me any longer. The point that I had been missing all along was that, you can still get to the source of the grid in much the same way that you get a Container.DataItem when binding to a Web DataGrid. So, provided that you can get the co-ordinates of the current cell in the grid, you can easily get the corresponding item in the IList source. Here's a couple of ways to get the current cell:

' based on keyboard activity
Private Sub dg_CurrentCellChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles dg.CurrentCellChanged
    Dim selectedItem As DataGridCell = dg.CurrentCell
    If selectedItem.RowNumber > -1 AndAlso selectedItem.ColumnNumber > -1 Then
        GetCellInfoByGridPosition(selectedItem.RowNumber, selectedItem.ColumnNumber)
    End If
End Sub

' based on mouse activity
Private Sub dg_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles dg.MouseDown
    If e.Button = MouseButtons.Left Then
        Dim info As DataGrid.HitTestInfo = dg.HitTest(e.X, e.Y)
        If info.Row > -1 AndAlso info.Column > -1 Then
            GetCellInfoByGridPosition(info.Row, info.Column)
        End If
    End If
End Sub

The GetCellInfoByGridPosition function is a helper method I wrote to abstract the task of getting the data from a set of co-ordinates:

Private Function GetCellInfoByGridPosition(ByVal row As Integer, ByVal col As Integer) As TableCellInfo
    Dim cm As CurrencyManager = CType(BindingContext(dg.DataSource, dg.DataMember), CurrencyManager)
    Dim cell As Object = CType(cm.List, DataView).Table.Rows(row).Item(col)
    If TypeOf cell Is TableCellInfo Then
        Return DirectCast(cell, TableCellInfo)
    Else
        Return Nothing
    End If
End Function

My GetCellInfoByGridPosition function checks to see whether or not the underlying cell is of Type TableCellInfo which is a custom Type of mine. Basically, I created the TableCellInfo class to allow me to bind additional data to the DataGrid cell. What that means is that, after my call to GetCellInfoByGridPosition, I have an instance of a TableCellInfo object to inspect and get data which was only avaiable at the time of binding. In my case it looked something like this:

Dim cellInfo As TableCellInfo = GetCellInfoByGridPosition(row, col)
ActualHours.Text = cellInfo.ActualHours
Comment.Text = cellInfo.Comment

No Comments