check all items under a parent node in Visual Basic - vb.net

I am trying to check all the childnodes under a parent node, the code I have so far only goes about 2-3 levels deep in the TreeView and I am looking to grab all nodes no matter how deep they are. Could someone shed some insight on this.
Below is the code:
Private Sub CheckChildNode(ByVal currNode As TreeNode)
'set the children check status to the same as the current node
Dim checkStatus As Boolean = currNode.Checked
For Each node As TreeNode In currNode.Nodes
node.Checked = checkStatus
CheckChildNode(node)
Next
End Sub
Private Sub CheckParentNode(ByVal currNode As TreeNode)
Dim parentNode As TreeNode = currNode.Parent
If parentNode Is Nothing Then Exit Sub
parentNode.Checked = True
For Each node As TreeNode In parentNode.Nodes
If Not node.Checked Then
parentNode.Checked = False
Exit For
End If
Next
CheckParentNode(parentNode)
End Sub
Private Sub treeview_AfterCheck(ByVal sender As System.Object, ByVal e As
System.Windows.Forms.TreeViewEventArgs) Handles treeview.AfterCheck
RemoveHandler treeview.AfterCheck, AddressOf treeview_AfterCheck
CheckChildNode(e.Node)
CheckParentNode(e.Node)
AddHandler treeview.AfterCheck, AddressOf treeview_AfterCheck
End Sub

In order to get all subnodes no matter how deep they are, you definitely need recursion.
That is, you take each direct child of a node and do the check for this node. And you also call the method to check subnodes for each child.
So here in Pseudocode.
node getParentNode(node child){
return child.parent
}
node checkNode(node n){
// perform check here for node n
if n is not valid {
return false!
}
// do children recursively
for each child in n.children{
// function calls itself!
checkNode(child)
}
}
Here's a recursion tutorial for vb.net. Here, here and here is you can find additional information.

Related

VB.NET - Check if child node if checked in TreeView

I am using Visual Basic .NET 2013 and I want to know which child nodes are checked in a treeview. I don't check parent nodes because the checkboxes are only in child nodes (I have disabled checkboxes in parent nodes, so they don't appear).
At the moment I am using one solution I found:
Private Sub TreeView1_AfterCheck(sender As Object, e As TreeViewEventArgs) Handles TreeView1.AfterCheck
Dim childNodeCK As TreeNode = e.Node
If childNodeCK.Checked = True Then
If e.Node.Parent Is Nothing = False Then 'detects a Child Node
TextBox1.Text = TextBox1.Text & childNodeCK.Text
MessageBox.Show("Checked: " & childNodeCK.Text)
End If
End If
If childNodeCK.Checked = False Then
If e.Node.Parent Is Nothing = False Then
MessageBox.Show("Unchecked: " & childNodeCK.Text)
End If
End If
End Sub
But I want to know if there is another solution, something like this (the following code doesn't show anything because when I click a button to run it, nothing happens):
For Each childNode As System.Windows.Forms.TreeNode In TreeView1.Nodes
If childNode.Checked = True Then
MessageBox.Show(childNode.Text)
End If
Next
because the idea is to click a button and obtain the name (text) of the child nodes that are checked at that moment. So I think I have to check one by one from the beginning to the end and if the child node is checked then execute some code.
To get all of the checked nodes, you would have to use a recursive function or a stacked list. I prefer the latter:
Private Function GetCheckedNodes() As List(Of TreeNode)
Dim result As New List(Of TreeNode)
'Get the root nodes
Dim nodes As New Stack(Of TreeNode)
For Each tn As TreeNode In TreeView1.Nodes
nodes.Push(tn)
Next
'Check each node and it's children
While nodes.Count > 0
Dim popNode As TreeNode = nodes.Pop
If popNode.Checked Then
result.Add(popNode)
End If
For Each tn As TreeNode In popNode.Nodes
nodes.Push(tn)
Next
End While
Return result
End Function
Then to use it:
For Each tn As TreeNode In GetCheckedNodes()
MessageBox.Show(tn.Text)
Next

How to Show appropriate form When Clicking Tree view child node in VB.net

I have Tree view that have 2 Root(Masters, Transactions) node and Each Root have 1 Child(See Tree view in Image)
Masters->Party master
Transactions->Order Acceptance
I want to Display frmPartymaster.vb form when clicking Party Master(child node)
and
Display frmorder.vb form when clicking Order Acceptance(child node)
I Tried Tree view After Select event(see below code)
Private Sub TreeView1_AfterSelect(ByVal sender As System.Object, ByVal e As System.Windows.Forms.TreeViewEventArgs) Handles TreeView1.AfterSelect
For Each node As TreeNode In Me.TreeView1.Nodes
GetChildren(node)
Next node
End Sub
Function GetChildren(ByVal parentNode As TreeNode) As List(Of String)
Dim nodes As List(Of String) = New List(Of String)
GetAllChildren(parentNode, nodes)
Return nodes
End Function
Sub GetAllChildren(ByVal parentNode As TreeNode, ByVal nodes As List(Of String))
For Each childNode As TreeNode In parentNode.Nodes
nodes.Add(childNode.Text)
GetAllChildren(childNode, nodes)
Next
End Sub
Above Code returns all childnode's names in Return nodes variable
Now I am Looking for
how to use nodes variable values
And how to show appropriate form when clicking child
node(I know child node haven't click event)
Tell me any other efficient way found instead of afterselect event
because it loop through all root node and child node each time
According to the code you provided, you are not even trying to instantiate another class depending on what node you have selected. All that is doing is adding nodes to a list, this is not needed...
This solution you can add any class where its type is Form.
There are a few ways this can be accomplished, but I just provided one way to do what you would like to achieve.
Imports System.Reflection
Public Class Form1
Private Const FORM_PARTY_MASTER As String = "frmPartyMaster"
Private Const FORM_ORDER As String = "frmorder"
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim mNode As New TreeNode With {.Text = "Masters"}
mNode.Nodes.Add(New TreeNode With {.Text = "Party Masters", .Tag = FORM_PARTY_MASTER})
Dim transNode As New TreeNode With {.Text = "Transaction"}
transNode.Nodes.Add(New TreeNode With {.Text = "Order/Acceptance", .Tag = FORM_ORDER})
TreeView1.Nodes.AddRange({mNode, transNode})
End Sub
Private Sub TreeView1_AfterSelect(sender As Object, e As TreeViewEventArgs) Handles TreeView1.AfterSelect
Dim obj As Form
Try
If e.Node.Tag IsNot Nothing Then
obj = CType(Activator.CreateInstance(Type.GetType("WindowsApplication5." & e.Node.Tag.ToString, False)), Form)
If obj IsNot Nothing Then
Using obj
obj.ShowDialog()
End Using
End If
End If
Catch ex As Exception
'handle your exception
End Try
End Sub
End Class
Explanation
Create some constants that would represent your forms.
The load routine was just to populate the data. You will notice I use the Tag property of the TreeNode, we will use this to get an instance of what form we would need.
The AfterSelect event is used. You will see how I create an instance of whatever control you would need; no case or if statements.
Make sure you change WindowsApplication5 to what your namespace would be.

Display all child nodes of selected node of treeview in textbox in vb.net

Not too sure on how to get around this.
I am able to display the current selected node in a textbox (or richtextbox) by doing the following:
Private Sub TreeView1_AfterSelect(sender As Object, e As TreeViewEventArgs) Handles TreeView1.AfterSelect
RichTextBox1.Text = e.Node.Text
End Sub
However, I can't figure out a way of displaying all child nodes of the selected parent.
Would anyone be able to point me in the right direction?
You need what is called a recursive subroutine to drill down into the child nodes of each node to iterate through them:
Private Sub TreeView1_AfterSelect(sender As Object, e As TreeViewEventArgs) Handles TreeView1.AfterSelect
Dim myNode As TreeNode = e.Node
TextBox1.Text = myNode.Text
GetChildNodes(myNode)
End Sub
Sub GetChildNodes(tnode As TreeNode)
'Iterate through the child nodes of the node passed into this subroutine
For Each node As TreeNode In tnode.Nodes
TextBox1.Text += node.Text
'If the node passed into this subroutine contains child nodes,
'call the subroutine for each one of them
'If you only want to display one level deep, then comment out the
'IF statement.
If tnode.Nodes.Count > 0 Then GetChildNodes(node)
Next
End Sub

Treeview get selected nodes third childnode

My treeview looks like this:
ParentNode
Childnode1
Childnode2
Childnode3 < I want to get the text of this node when you click on the parentnode
Childnode4
Childnode5
Thanks
It is as simple as using the indexer property of the Nodes collection of your node, like this:
YourNode.Nodes(2).Text
If you have handled NodeMouseClick event of your TreeView, the second parameter e as TreeNodeMouseClickEventArgs can be used like this:
Public Sub YourTreeView_AfterSelect(sender As Object, e As System.Windows.Forms.TreeNodeMouseClickEventArgs)
If YourTreeView.SelectedNode.Nodes.Count > 2 Then
MsgBox(YourTreeView.SelectedNode.Nodes(2).Text)
Else
MsgBox("No 3rd node is available.")
End Sub
Got what I was looking for thanks to #dotNET
Private Sub TreeView1_Click(sender As Object, e As EventArgs) Handles TreeView1.AfterSelect
If TreeView1.SelectedNode IsNot Nothing AndAlso TreeView1.SelectedNode.Nodes.Count > 2 Then
Link = TreeView1.SelectedNode.Nodes(2).Text
End If
End Sub
Thanks

How to add a new treeview at the selected node?

I have a treeview with four levels; parent, child, grandchild, great-grandchild. My selectednode is at the grandchild level.
What I'm trying to do is to create a new "Treeview" at the grandchild - NO, I dont wnat to create a new node to the "selectednode" (grandchild). So it should be somelike this:
parent
child
grandchild (New TreeView) PARENT which was grandchild
great-grandchild child
great-grandchild child
grandchild grandchild
It would be similar to a parent table where the mother and father went off and had new childern with a different spouse other than the spouse of there existing children.
Private Sub PopulateRootLevel()
' query to find first round of parent
PopulateNodes(dt, JCATreeView.Nodes)
End Sub
Private Sub PopulateNodes(ByVal dt As DataTable, ByVal nodes As TreeNodeCollection)
For Each dr As DataRow In dt.Rows
Dim tn As New TreeNode()
tn.Text = dr("TITLE").ToString()
tn.Value = dr("Parent_ID").ToString()
nodes.Add(tn)
'If node has child nodes, then enable on-demand populating
tn.PopulateOnDemand = (CInt(dr("childnodecount")) > 0)
Next
End Sub
Private Sub PopulateSubLevel(ByVal parentid As Integer, ByVal parentNode As TreeNode)
' query to find children of parent with child node count of parent
da.Fill(dt)
PopulateNodes(dt, parentNode.ChildNodes)
End Sub
Protected Sub TreeView1_TreeNodePopulate(ByVal sender As Object, _
ByVal e As System.Web.UI.WebControls.TreeNodeEventArgs) Handles TreeView1.TreeNodePopulate
' add a test to determine if this is from TreeView1 or Sub_TreeView1
PopulateSubLevel(CInt(e.Node.Value), e.Node)
End Sub
Protected Sub TreeView1_SelectedNodeChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles TreeView1.SelectedNodeChanged
Dim selected_parent_id As Integer = sender.SelectedNode.value
Parent_to_NEW_TREEVIEW_PopulateSubLevel(selected_parent_id, sender.SelectedNode)
End Sub
Private Sub Sub_TreeView1_PopulateSubLevel(ByVal parent_id As Integer, ByVal parentNode As TreeNode)
' Query to get new children of parents
da.Fill(dt2)
Sub_TreeView1_PopulateNodes(dt2, parentNode.ChildNodes)
End Sub
Private Sub Sub_TreeView1_PopulateNodes(ByVal dt As DataTable, ByVal nodes As TreeNodeCollection)
For Each dr As DataRow In dt.Rows
Dim tn As TreeNode = New TreeNode()
'tn = parentBCNode.Nodes.Add("NEW_PARENT_TREEVIEW")
' query to get child on the new parent treeview
tn.Text = dr("New parent title").ToString()
tn.Value = dr("New_parent_ID").ToString()
nodes.Add(tn)
'If node has child nodes, then enable on-demand populating
tn.PopulateOnDemand = (CInt(dr("childnodecount")) > 0)
Next
End Sub
You can't do that.
A TreeView can not have as one of its child nodes another TreeView control. The only thing you can do is assign the TreeView to the tag property of a TreeNode, but that will not be displayed (obviously).
I don't understand why you would want to do that, unless you want a different drawing behavior for that grand-child sub-tree.
You can make use of the treeNode.Level property to find out at which level that node is. And again you can create a custom object(that has all your required information) and store it in the treeNode.Tag property.