Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations bkrike on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Can't Get TreeView Loaded 2

Status
Not open for further replies.

mdwg2020

Programmer
Feb 17, 2005
51
US
This is probably pretty simple for everyone, but I can't quite understand the process. I have never used a treeview before and am trying to populate one with information that I am pulling from a SQL Server. I pulled the information that I needed into a dataset. In the table, I have information like this:

EmpPK, MgrEmpFK

Each employee has a Primary Key. The same table holds the Primary Key of their manager, that is the obvious relation. It seems like it would be simple to build the hierarchy because it is clearly in the tables, but I don't understand how. Anybody have any ideas?
 
Are you trying to create a node for a manager and then sub nodes for employees?

If this is the case, what you want to do is loop through the rows of your manager table and add nodes. While inside the loop, you can do a .Select() on the employee table for employees who belong to that manager row. You then add the sub nodes to the current node in the loop.
 
Yes RiverGuy, that is exactly what I am trying to do. I need to do that so that I can load the data into a treeview. The table that I am pulling from uses adjacency, and I am having a hard problem doing what you said. Do I have to create a temp table to store the node information in? Or can I just return the node information using a stored procedure.

Sorry for my ignorance, I usually have to see examples to understand.

Thanks
 
Code:
MasterTable = MyDataSet.Tables("MasterTable")
DetailTable = MyDataSet.Tables("DetailTable")

For Each mr As DataRow In MasterTables.Rows()
  Dim MasterNode As TreeNode = MyTreeview.Nodes.Add(mr.Item("ColumnName")) 'Add a master node with your data row
  For Each dr As DataRow In DetailTable.Select("ForeignKeyFeild=" & mr.Item("KeyField"))
    MasterNode.Nodes.Add(dr.Item("ColumnName"))
  Next
Next

This is the easiest way to do it. In the future, you can always create DataRelations in your DataSet and use the .GetChildRows() function--you may want to read about that as well....but it involves more code setting up the relations in ADO.Net
 
Thanks RiverGuy, everything makes since except for one thing. I am pulling this information off of one table, should I actually populate the dataset with the same information twice so that I can show a relationship between the two seperate tables, (ie. "MasterTable" and "DetailTable")?

I believe that is what I'm doing. Thanks for all of your help. I also read about creating the DataRelations within the DataSet, but it also always showed using 2 tables, whereas I am only using one.
 
Oh. So you are using in effect, a recursive relationship? I'm not sure if it is possible to do this in a DataRelation. But, you can still do this with one table, without using a .Select(), although it might be slow if have a bunch of data. You would just loop through the DataTable twice, and use an If statement.

 
Hey RiverGuy, I'm getting closer, I was able to get everyone from the table into the tree view, all as parentnodes using the following code:

For Each mr As DataRow In MasterTable.Rows()
Dim MasterNode As TreeNode
MasterNode = New TreeNode(mr.Item(1))
tvEmployeeTree.Nodes.Add(MasterNode)
Next

Now, you say I need to loop through the table again, but obviously I need to add the people under there correct managers, and you say that it can be done with a simple if statement?

I appreciate all your help, I have never used the treeview control before, and before using it, I was pretty comfortable with programming in Visual Basic.
 
Something like

If DetailDataRow.Item("MasterID") = MasterDataRow.Item("ID") Then
'Add It
End If
 
I have tried everything now. I have about 6 levels deep of employees, and I had to actually embed code much like a recursive function. I have tried tons of different things. I used enumerators, but they only enumerated throught the first level of nodes. I used the enumerators with the nodes collection, but apparently a node collection doesn't actually contain all of the nodes in the entire tree, and the first level of nodes. This control is very difficult for me and I just don't understand why. My situation again was that I have one data table that has all of my employees, the table also has the managers employee key, and I'm trying to show this hierarchy in a treeview.

EmpPK MgrsEmpFK
110 112

This would should that employee 110's manager is employee 112, I know everyone is familiar with the setup. Well this is the crappy code that I wrote, and it only worked because I knew how many levels I had nested, but its still very sloppy code, can anyone help?

Private Sub FillTree()
Dim i, j, k, l, m, n, o As Integer
Dim aNode, bNode, cNode, dNode, eNode, fNode, gNode As TreeNode

aNode = tvEmployeeTree.TopNode()
For i = 0 To intRows - 1
If (dsResults.Tables("Employees").Rows(i).Item("MgrEmpFK").ToString = aNode.Tag.ToString) Then
Dim nTreeNode As New TreeNode
nTreeNode.Tag = dsResults.Tables("Employees").Rows(i).Item("EmpFK")
nTreeNode.Text = dsResults.Tables("Employees").Rows(i).Item("Emp_No") & " - " & dsResults.Tables("Employees").Rows(i).Item("EmpFullName1")
dsResults.Tables("Employees").Rows(i).Item("MgrEmpFK") = 0
aNode.Nodes.Add(nTreeNode)

intNodesAdded += 1
End If
Next

For Each bNode In aNode.Nodes()
For j = 0 To intRows - 1
If (dsResults.Tables("Employees").Rows(j).Item("MgrEmpFK").ToString = bNode.Tag.ToString) Then
Dim nTreeNode As New TreeNode
nTreeNode.Tag = dsResults.Tables("Employees").Rows(j).Item("EmpFK")
nTreeNode.Text = dsResults.Tables("Employees").Rows(j).Item("Emp_No") & " - " & dsResults.Tables("Employees").Rows(j).Item("EmpFullName1")
dsResults.Tables("Employees").Rows(j).Item("MgrEmpFK") = 0
bNode.Nodes.Add(nTreeNode)

intNodesAdded += 1
End If
Next
For Each cNode In bNode.Nodes()
For k = 0 To intRows - 1
If (dsResults.Tables("Employees").Rows(k).Item("MgrEmpFK").ToString = cNode.Tag.ToString) Then
Dim nTreeNode As New TreeNode
nTreeNode.Tag = dsResults.Tables("Employees").Rows(k).Item("EmpFK")
nTreeNode.Text = dsResults.Tables("Employees").Rows(k).Item("Emp_No") & " - " & dsResults.Tables("Employees").Rows(k).Item("EmpFullName1")
dsResults.Tables("Employees").Rows(k).Item("MgrEmpFK") = 0
cNode.Nodes.Add(nTreeNode)

intNodesAdded += 1
End If
Next
For Each dNode In cNode.Nodes()
For l = 0 To intRows - 1
If (dsResults.Tables("Employees").Rows(l).Item("MgrEmpFK").ToString = dNode.Tag.ToString) Then
Dim nTreeNode As New TreeNode
nTreeNode.Tag = dsResults.Tables("Employees").Rows(l).Item("EmpFK")
nTreeNode.Text = dsResults.Tables("Employees").Rows(l).Item("Emp_No") & " - " & dsResults.Tables("Employees").Rows(l).Item("EmpFullName1")
dsResults.Tables("Employees").Rows(l).Item("MgrEmpFK") = 0
dNode.Nodes.Add(nTreeNode)

intNodesAdded += 1
End If
Next
For Each eNode In dNode.Nodes()
For m = 0 To intRows - 1
If (dsResults.Tables("Employees").Rows(m).Item("MgrEmpFK").ToString = eNode.Tag.ToString) Then
Dim nTreeNode As New TreeNode
nTreeNode.Tag = dsResults.Tables("Employees").Rows(m).Item("EmpFK")
nTreeNode.Text = dsResults.Tables("Employees").Rows(m).Item("Emp_No") & " - " & dsResults.Tables("Employees").Rows(m).Item("EmpFullName1")
dsResults.Tables("Employees").Rows(m).Item("MgrEmpFK") = 0
eNode.Nodes.Add(nTreeNode)

intNodesAdded += 1
End If
Next
For Each fNode In eNode.Nodes()
For n = 0 To intRows - 1
If (dsResults.Tables("Employees").Rows(n).Item("MgrEmpFK").ToString = fNode.Tag.ToString) Then
Dim nTreeNode As New TreeNode
nTreeNode.Tag = dsResults.Tables("Employees").Rows(n).Item("EmpFK")
nTreeNode.Text = dsResults.Tables("Employees").Rows(n).Item("Emp_No") & " - " & dsResults.Tables("Employees").Rows(n).Item("EmpFullName1")
dsResults.Tables("Employees").Rows(n).Item("MgrEmpFK") = 0
fNode.Nodes.Add(nTreeNode)

intNodesAdded += 1
End If
Next
For Each gNode In fNode.Nodes()
For o = 0 To intRows - 1
If (dsResults.Tables("Employees").Rows(o).Item("MgrEmpFK").ToString = gNode.Tag.ToString) Then
Dim nTreeNode As New TreeNode
nTreeNode.Tag = dsResults.Tables("Employees").Rows(o).Item("EmpFK")
nTreeNode.Text = dsResults.Tables("Employees").Rows(o).Item("Emp_No") & " - " & dsResults.Tables("Employees").Rows(o).Item("EmpFullName1")
dsResults.Tables("Employees").Rows(o).Item("MgrEmpFK") = 0
gNode.Nodes.Add(nTreeNode)

intNodesAdded += 1
End If
Next
Next
Next
Next
Next
Next
Next
End Sub

This is terrible. The first part I just add the root node because I know exactly who it is, but then I loop through to add everyone of the additional employees under them. Sorry to all, this is just killing me. I've spent hours on this and can't figure it out. By the way, even after the tree is populated TreeView.Nodes.Count returns only the top level nodes, I'm really confused. Thanks again!
 
According to this page, you can do recursive DataRelations in ADO.Net.
But what it seems like you are saying is that although you have 6 levels of employees you may or may not have more at some point?

Try setting up a DataRelation like that tutorial has done, then, I think you could do something like this:

Code:
For Each dr As DataRow In Table.Rows
  If dr("Manager") = 0 Then 'No Manager 
    Dim n As TreeNode
    n = MyTreeView.Nodes.Add(dr("EmployeeName"))
  End If
Next

Code:
Sub AddChildrenRecursive(parent_row As DataRow, parent_node As TreeNode)
  For Each dr As DataRow in parent_row.GetChildRows("RelationName")
    Dim n As TreeNode
    n = parent_nodes.Nodes.Add(dr("EmployeeName"))
    AddChildrenRecursive(dr, n)
  Next
End Sub
 
Oops, first code block should have been

Code:
For Each dr As DataRow In Table.Rows
  If dr("Manager") = 0 Then 'No Manager 
    Dim n As TreeNode
    n = MyTreeView.Nodes.Add(dr("EmployeeName"))
    AddChildrenRecursive(dr, n)
  End If
Next
 
Hey RiverGuy, thanks again. I am going to check out that article, it sounds like what I have been looking for but couldn't find, and you are right, that is what is going on. It is possible to have more or fewer levels of hierarchy. In my example, once I added the node, I reset the key to zero so that it would never be added again, but you're right, there has to be a better way. I'll see if I can do what is suggested.

Thanks,

Brooks
 
2 more quick questions, and I'm still working on getting the treeview loaded in a recursive fashion, I've kind of had to move on since I have a fix for now.

How do I programmatically select a node in the treeview? I attempted to set the tv.selectedNode() property to a node, but that didn't work, or maybe it did, so here is my second question.

How do you keep that selection visible when you start using other controls? For instance I have radio buttons on the same form, once I click out of the tree onto another control, I don't see my selection as being highlighted anymore, I would like that to stay selected.
 
Well, I found the hideselection option and cut it to false fixing my selection problem when the control loses focus. Still don't know how to programmatically select a node.

And how do you insert the little code boxes into the forum?
 
to use the code block put a [bold][[/bold] then the word [bold]code[/bold] then a [bold]][/bold], at the end of the code block do the same except [bold]/code[/bold].

-Rick

----------------------
 
to use the code block put a [ then the word code then a ], at the end of the code block do the same except /code.

-Rick

PS: Sorry bout that last post, my arm decided I was done instead of trying to preview.

----------------------
 
I found out that I was actually selected the nodes correctly with code the problem was just that I didn't have the hideselection to false, and the treeview wasn't selected initially.

I used the following code to recursively search through the tree and select the person who actually logged into the system, do you think I could use this exact same logic to load the tree recursively?

CallResursive(tv)
tv.Select()

Private Sub CallRecursive(ByVal aTreeView As TreeView)
Dim n As TreeNode
For Each n In aTreeView.Nodes
SearchAndSelect(n)
Next
End Sub

Private Sub SearchAndSelect(ByVal n As TreeNode)
System.Diagnostics.Debug.WriteLine(n.Text)
Dim aNode As TreeNode
For Each aNode In n.Nodes
If (aNode.Text.ToString.Substring(0, 4) = SystemInformation.UserName.ToString) Then
tvEmployeeTree.SelectedNode() = aNode
Exit Sub
End If
SearchAndSelect(aNode)
Next
End Sub
 
I still haven't been able to try the recursive fill method, but I'm going to try again today. I've almost got the UI done, this is the last piece, hopefully I can figure it out. The recursive search worked perfectly.
 
I wasn't able to build the data relation within my dataset, kept getting various messages. I guess I want be able to recursively call datarows unless I can figure out how to setup the relationship the way they did in that C# program you showed me. Anyway, I guess I will keep digging until I can find something.
 
I attempted to do the following:

Code:
Private Sub RelateData()
     Dim drEmployee As DataRelation
     drEmployee = New DataRelation("SelfReferencing", dsResults.Tables(1).Columns("Emp_MgrEmpFK"), dsResults.Tables(1).Columns("Emp_PK), false)
     dsResults.Relations.Add(drEmployee)
End Sub

Private Sub FillTree()
     For Each dr As DataRow In Table.Rows
         If (dr("Emp_MgrEmpFK") = 2261) Then 'CIO RootNode 
             Dim n As New TreeNode
             n.tag = dr("Emp_PK)
             n.text = dr("Emp_FName")
             tvEmployeeTree.Nodes.Add(n)
             AddChildrenRecursive(dr, n)
         End If
     Next
End Sub

Private Sub AddChildrenRecursive(drParentRow As DataRow, tnParentNode As TreeNode)
    For Each dr As DataRow in drParentRow.GetChildRows("SelfReferencing")
        Dim n As New TreeNode
        n.tag = dr("Emp_PK)
        n.text = dr("Emp_FName")
        tnParentNode.Nodes.Add(n)
        AddChildrenRecursive(dr, n)
    Next
End Sub

When I run this, I get the root node, but now child nodes period. I step through the debug, and when it comes down to AddChildrenRecursive, it checks the line:

Code:
For Each dr As DataRow in drParentRow.GetChildRows("SelfReferencing")

But then it goes outside of the for block as if no children exists. It should find 8 child rows for that row but it doesn't find anything.

Do you have any ideas? I will keep playing with it.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top