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
plusRect = New Rectangle(x, y + 5, plusRectWidth, plusRectHeight)
g.DrawRectangle(Pens.DimGray, plusRect)
g.FillRectangle(ButtonExpandDefaultColor, plusRect)
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:
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:
Dim cpDgv As New CPDataGridView
cpDgv.Expandable = True
cpDgv.NodeControl = btnClose
The Events
There are four custom events of this control:
1. RowExpanding(): This events raised before draw the node control. For example:
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
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
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
Private Sub dgvGrandParent_RowCollapsing() Handles dgvGrandParent.RowCollapsing
connection.Close()
End Sub
4. RowCollapsed(). Raised after the NodeControl removed from current row of datagridview
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:
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