Populate Treeview with Database

chadbengen

New member
Joined
Mar 12, 2006
Messages
2
Programming Experience
Beginner
I'm populating a treeview with data from an mdb file. My questions are:
1. Is there a faster method? It's not "instantaneous" like a datagrid would be.
2. Is there a way to add to each parent the number of childnodes in parenthesis? ...."Parentnode (3)" Ideally I would like the "(3)" to be a different color, like blue.
3. Is there a way to "columnize" the text in a node? For instance, I want the calldate to be formatted as "ddd mmm/dd/yyyy" but unless I use courier font the mmm/dd/yyyy will not be lined up down the list.

I would use a datagrid except that I want to be able to collapse rows with the same date. Speed is important becuase I plan on refreshing it often.

Thanks for your help!

Here's the code I'm using:
VB.NET:
[SIZE=2][COLOR=#0000ff]     Dim calldate As String = Nothing
        Dim calltime As String = Nothing
        Dim callreason As String = Nothing
        Dim LastNodeSet As String = Nothing
        Dim NodeRootRow As Integer = -1[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]     TreeView1.ImageList = ImageList1
        TreeView1.ShowPlusMinus = False
        TreeView1.ShowRootLines = False
        TreeView1.ShowLines = False
        TreeView1.Nodes.Clear()[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]     Dim X As Long
        Dim Y As Long[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]     Dim cnstr As String = "Provider=microsoft.jet.oledb.4.0;" & _
                              "data source=C:\Documents and Settings\Owner\My Documents\Work\Access\afterhours.mdb;"[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]     Dim cn As System.Data.OleDb.OleDbConnection = New System.Data.OleDb.OleDbConnection(cnstr)
        cn.Open()
        Dim Sql As String = "SELECT calldate, calltime, callreasonid FROM main ORDER BY calldate desc"
        Dim objCommand As OleDb.OleDbCommand = New OleDb.OleDbCommand(Sql, cn)[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]     Dim Reader As OleDb.OleDbDataReader = objCommand.ExecuteReader()[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]     While Reader.Read()
            On Error Resume Next
            calldate = Format(Reader.Item(0), "MMM dd, yyyy")
            calltime = Reader.Item(1)
            callreason = Reader.Item(2)
            calltime = calltime & "  " & callreason
            If calldate = LastNodeSet Then GoTo dimchild[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]         Dim parent As New TreeNode(calldate, 1, 0)
DimChild:
            Dim child As New TreeNode(calltime, 2, 0)[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]         If calltime = Nothing Then
                TreeView1.Nodes.Add(parent)
                LastNodeSet = calldate
                NodeRootRow += 1
            Else
                If calldate = LastNodeSet Then
                    parent.Nodes.Add(child)[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]             Else
                    TreeView1.Nodes.Add(parent)
                    parent.Nodes.Add(child)
 
                    LastNodeSet = calldate
                    NodeRootRow += 1
                End If
            End If
            calldate = Nothing : calltime = Nothing
        End While
        cn.Close()
        cn = Nothing
    End Sub[/COLOR][/SIZE]
 
1. "To maintain performance while items are added one at a time to the TreeView, call the BeginUpdate method. The BeginUpdate method prevents the control from painting until the EndUpdate method is called."

Another tip, avoid declaring variables inside extensive loops, it's a time consuming process. There is no need for you to declare parent or child TreeNode each loop. Declare them outside the loop, and just assign the new instance to 'parent' and/or 'child'.

2. Count childs and add to text of parentnode you already got reference to before getting the next parent.
(or Walk the tree again after adding all the nodes to see how many TreeNode.Nodes.Count there is, adding to the existing text.)

If you want to format the text of individual treenodes you have to set the DrawMode of TreeView to OwnerDrawText and handle the text drawing in TreeView.DrawNode event handler.

Since the DrawNode method is used to draw all nodes, some logic have to be applied here, for instance for 'text (#)' you want bracket part in blue, detecting start bracket in a text is easy but the question is if it's valid formatting for any node containing a bracket. So one could be clever and choose some character that will make it easy to handle drawing of any particular node according to the formatting rules. Another option is of course to add some info to the Tag property of each node when it is added to make life easier when doing the custom drawing.

3. It may not look good with different fonts for nodes in same tree, but you'll be getting a hard time to 'columnize' the dates without a fixed type font like Courier. Different fonts for different nodes is also something that have to be done with OwnerDrawText.

Avoid GOTO, there is no need for this statement that only adds confusion to the code. It was only kept in VB6 for backward compability when upgrading older versions projects, and still is for some strange reason in VB.Net. It should not be used when coding today. (reference: spaghetti code)
 
Thanks for the feedback. I'm looking into the ownerdraw features and I think I've found a way to use that to do my (#) in blue.
 
Back
Top