Reputation: 181
Good Day,
I have two List of objects (say for e.g. MyObjList as new List(of Integer) ) and based on their indices I want to build up a treeview starting from item 0 and end with last item in the list. I want these objects to appear something like below. I can add first node but then after that can't figure how to add next node as child of each previously added node (if that makes sense). Would appreciate your help. I have attached an image to give better understanding of how I want it to look like as against to what I am getting at the moment based on below answers.
0-->
1
-->
2
-->
3-->
4
Dim myObjList As New List(Of integer)
myObjList.Add("0")
myObjList.Add("1")
myObjList.Add("2")
myObjList.Add("3")
myObjList.Add("4")
Can we achieve this?
Upvotes: 2
Views: 5286
Reputation: 4489
If I have got this right, you are trying to add Nodes
so that the TreeView
looks like this:
This is what it would look like manually:
TreeView1.Nodes.Add(list(0).ToString())
TreeView1.Nodes(0).Nodes.Add(list(1).ToString())
TreeView1.Nodes(0).Nodes(0).Nodes.Add(list(2).ToString())
TreeView1.Nodes(0).Nodes(0).Nodes(0).Nodes.Add(list(3).ToString())
TreeView1.Nodes(0).Nodes(0).Nodes(0).Nodes(0).Nodes.Add(list(4).ToString())
This of course is a real pain and isn't scalable. What I would look at instead is recursively adding child Nodes
to the TreeView
like such:
Public Class Form1
Dim list As New List(Of Integer)
Private Sub AddMoreChildren(ByVal parent As TreeNode)
If parent.Level < list.Count - 1 Then
Dim child As New TreeNode(list(parent.Level + 1).ToString())
parent.Nodes.Add(child)
AddMoreChildren(child)
End If
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
list.Add(0)
list.Add(1)
list.Add(2)
list.Add(3)
list.Add(4)
Dim root As New TreeNode(list.First.ToString())
AddMoreChildren(root)
TreeView1.Nodes.Add(root)
End Sub
End Class
From the code above you will achieve the same result as seen shown in the screenshot.
The beauty of this is that the code will continue to call AddMoreChildren
until all items in the List
have been added.
Edited to incorporate two lists
If you have two lists then what I would look at doing is bringing them together to create a distinct List
using Concat and Distinct.
Note that I have now changed my
List
s to be of typeString
for this example and no longer need to use.ToString
when setting the value.
Public Class Form1
Dim firstList As New List(Of String)
Dim secondList As New List(Of String)
Dim mainList As New List(Of String)
Private Sub AddMoreChildren(ByVal parent As TreeNode)
If parent.Level < mainList.Count - 1 Then
Dim child As New TreeNode(mainList(parent.Level + 1))
parent.Nodes.Add(child)
AddMoreChildren(child)
End If
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
firstList.Add("S")
firstList.Add("A3")
firstList.Add("U13")
firstList.Add("ABC")
firstList.Add("PQ")
firstList.Add("1234")
secondList.Add("S")
secondList.Add("A3")
secondList.Add("U13")
secondList.Add("XYZ")
secondList.Add("ST")
secondList.Add("5678")
mainList = firstList.Concat(secondList).Distinct().ToList()
Dim root As New TreeNode(mainList.First)
AddMoreChildren(root)
TreeView1.Nodes.Add(root)
End Sub
End Class
This will give you the following output:
Edit based on OP's update
This is what the OP is after based on the update:
This requires a little more code and isn't as neat but it does do the job. In this I have to bring in another variable called index
. This is purely to keep track of the current index in mainList
instead of using If parent.Level
.
I also have to manipulate mainList
quite a bit so I'll try to explain in bits.
First let's use Intersect. This is used to get a list where values are found in both firstList
and secondList
leaving us with S, A3 and U13:
Dim root As TreeNode
mainList = firstList.Intersect(secondList).ToList()
root = New TreeNode(mainList.First)
Now that we have these let's go ahead and add them to the TreeView
:
index = 1
AddMoreChildren(root)
TreeView1.Nodes.Add(root)
I set index
to 1 here because I already have the root node and want to start at A3 when I go into AddMoreChildren
. There has also been a slight change to the AddMoreChildren
method:
Private Sub AddMoreChildren(ByVal parent As TreeNode)
If index < mainList.Count Then
Dim child As New TreeNode(mainList(index).ToString())
parent.Nodes.Add(child)
index += 1
AddMoreChildren(child)
End If
End Sub
Note the use of
index
now instead ofparent.Level
.
Next, since you want to branch out from U13 we need to get the index of this. This is done quite simply:
Dim indexOfLastNode As Integer = mainList.Count - 1
Next we set the U13 as the root node:
root = GetLastAddedChildNode(TreeView1.Nodes(0), indexOfLastNode)
The code for GetLastAddedChildNode
is:
Private Function GetLastAddedChildNode(ByVal parentNode As TreeNode,
ByVal level As Integer) As TreeNode
Dim newNode As New TreeNode
For Each node As TreeNode In parentNode.Nodes
If node.Level = level Then
newNode = node
Exit For
End If
newNode = GetLastAddedChildNode(node, level)
Next
Return newNode
End Function
Then we manipulate the mainList
so that we get all values from firstList
that aren't in secondList
. This leaves us with ABC, PQ and 1234. We do this by using Except. We can then call AddMoreChildren
and add ABC, PQ and 1234 to U13.
Note, don't forget to reset
index
to 0 before you callAddMoreChildren
so that we can get all the items inmainList
added.
We then do the same for the secondList
using Except
. Here is the full code in one full swoop. It may make more sense:
Public Class Form1
Dim firstList As New List(Of String)
Dim secondList As New List(Of String)
Dim mainList As New List(Of String)
Dim index As Integer
Private Sub AddMoreChildren(ByVal parent As TreeNode)
If index < mainList.Count Then
Dim child As New TreeNode(mainList(index).ToString())
parent.Nodes.Add(child)
index += 1
AddMoreChildren(child)
End If
End Sub
Private Function GetLastAddedChildNode(ByVal parentNode As TreeNode,
ByVal level As Integer) As TreeNode
Dim newNode As New TreeNode
For Each node As TreeNode In parentNode.Nodes
If node.Level = level Then
newNode = node
Exit For
End If
newNode = GetLastAddedChildNode(node, level)
Next
Return newNode
End Function
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
firstList.Add("S")
firstList.Add("A3")
firstList.Add("U13")
firstList.Add("ABC")
firstList.Add("PQ")
firstList.Add("1234")
secondList.Add("S")
secondList.Add("A3")
secondList.Add("U13")
secondList.Add("XYZ")
secondList.Add("ST")
secondList.Add("5478")
Dim root As TreeNode
mainList = firstList.Intersect(secondList).ToList()
root = New TreeNode(mainList.First)
index = 1
AddMoreChildren(root)
TreeView1.Nodes.Add(root)
Dim indexOfLastNode As Integer = mainList.Count - 1
If TreeView1.Nodes.Count = 1 Then
root = GetLastAddedChildNode(TreeView1.Nodes(0), indexOfLastNode)
mainList = firstList.Except(secondList).ToList()
If root.Text.Equals(firstList(indexOfLastNode)) Then
index = 0
AddMoreChildren(root)
mainList = secondList.Except(firstList).ToList()
index = 0
AddMoreChildren(root)
End If
End If
End Sub
End Class
Here is a screenshot of the output:
Upvotes: 3
Reputation: 2750
Put together this code for you:
Dim tmpNode As TreeNode = Nothing
For Each num In myObjList.Reverse
Dim newNode = New TreeNode(num.ToString)
If tmpNode IsNot Nothing Then
newNode.Nodes.Add(tmpNode)
End If
tmpNode = newNode
Next
Goes through the list in reverse and adds each node as a child of the last.
EDIT: Did this one too, doesn't require reversing your list
Dim topNode As TreeNode = Nothing
Dim latestNode As TreeNode = Nothing
For Each num In myObjList
Dim tmpNode = New TreeNode(num.ToString)
If myObjList.IndexOf(num) = 0 Then
topNode = tmpNode
latestNode = topNode
Else
latestNode.Nodes.Add(tmpNode)
latestNode = tmpNode
End If
Next
Upvotes: 1