Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / VB

Custom DataGridView (Nested DataGridView / TreeGridView)

5.00/5 (4 votes)
12 Nov 2016CPOL2 min read 22.8K   1.5K  
This control is a datagridview that can contain control as its node, and it can contain unlimited node control

 

Introduction

Yes you can set an unlimited control into this datagridview, with many type of control such as:

  • Button
  • Picture Box
  • Datagridview it self
  • TabControl
  • etc

And there are two custom properties of this control:

  • Expandable: when the value is true, it will draw the expand button. 
  • NodeControl: Here is the property you can set the existing control on your form as its node child.

Background

I was having trouble with control to present my 'parent-child-child' data. So far I failed to find such control on the internet, especially a real nested datagridview. The biggest problem of mine was I want to put events on the node control of the datagridview easly. Then I created this one.

 

The idea of this class are: 

1. Create or draw 'Button Like' for the user to expand or collapse the child control

VB.NET
                'Here's the example as you can see in the drawExpandButton() method, wich called in the overriden OnPaint method:

                'DRAW THE EXPAND BUTTON
                plusRect = New Rectangle(x, y + 5, plusRectWidth, plusRectHeight)
                g.DrawRectangle(Pens.DimGray, plusRect)
                g.FillRectangle(ButtonExpandDefaultColor, plusRect)

                'DRAW THE STRING (the '+' letter)
                g.DrawString(plusString, plusFont, plusBrush, x - 1, y + 1)

2. Clone the existing control on your windows form, than set the returned data (As Control) to the NodeControl properties

Example:

VB.NET
    Private Function cloneControl(ByVal ctrl As Control) As Control
        Dim resultControl As Control
        Return resultControl
    End Function

 

Using the code

This is you may not like. The node control is static, it doesnt generate the node(or child) control dynamicly at run time. So you need to add control you want to be as its child on your form.

The Properties

There are two ways to put a node child in it:

1. At design time: simply set the value of NodeControl property with your existing control in the form

2. Programmatically:

VB.NET
Dim cpDgv As New CPDataGridView 'The long name of this control with its namespace is: CodeProject.Windows.ControlLib.CPDataGridView
cpDgv.Expandable = True
cpDgv.NodeControl = btnClose 'Assume that you already have a control in your windows form named btnClose

The Events

There are four custom events of this control:

1. RowExpanding(): This events raised before draw the node control. For example:

 

VB.NET
    Dim connection As New SqlClient.SqlConnection
    Dim cmd As New SqlClient.SqlCommand
    Dim adapter As New SqlClient.SqlDataAdapter

    Private Sub dgvGrandParent_RowExpanding() Handles dgvGrandParent.RowExpanding
        'You made a connection before the row of this control expanded
        connection.Open()
    End Sub

 

2. RowExpanded(): The event raised after draw the node control. Here's the example:

After you made the connection in the RowExpanding event, you fill a DataTable object the set it as the datagridview child's datasource

 

VB.NET
    Private Sub dgvGrandParent_RowExpanded() Handles dgvGrandParent.RowExpanded
        Dim dt As New DataTable
        cmd.CommandText = "SELECT * FROM employee"
        cmd.Connection = connection
        adapter.SelectCommand = cmd
        adapter.Fill(dt)
        dgvChild.DataSource = dt
    End Sub

 

3. RowCollapsing(). This event raised before removing the nodecontrol from current row

 

VB.NET
    Private Sub dgvGrandParent_RowCollapsing() Handles dgvGrandParent.RowCollapsing
        connection.Close()
    End Sub

 

4. RowCollapsed(). Raised after the NodeControl removed from current row of datagridview

VB.NET
    Private Sub dgvGrandParent_RowCollapsed() Handles dgvGrandParent.RowCollapsed
        MsgBox("The connection was closed")
    End Sub

BUG AND PROBLEM

Yes there are bugs,

1. In the Paint Event. When you scroll down the row, you'll find a 'button like' or the expand button on the row header first visible row. but I'v put a tricky code to cover up this issue with this code:

VB.NET
g.FillRectangle(Brushes.GhostWhite, 2, 2, Me.RowHeadersWidth - 2, Me.ColumnHeadersHeight - 2)

in both drawCollapseButton() method and the drawExpandButton() method:

2. I found it's flickering and slow when you expand a lot of node child/node control.

 

Hope this project could be helpful

License

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