I have tree view which has grandfather node and inside of this grandfather there is parent and inside this parent there is son node.
How I can get the names of this grandfather , parent and son nodes.
I already did the code to work when the user double clicks on the son node, but still I am unable to get the names for the grandfather, parent and child nodes.
here is my code:
Private Sub TreeView1_NodeMouseDoubleClick(sender As Object, e As TreeNodeMouseClickEventArgs) Handles TreeView1.NodeMouseDoubleClick
Dim ClickPoint As Point = New Point(e.X, e.Y)
Dim ClickedChildNode As TreeNode = TreeView1.GetNodeAt(ClickPoint)
If ClickNode Is Nothing Then
Exit Sub
End If
Dim strGrandFatherName As String
Dim strParentName As String
Dim strSonName As String
strGrandFatherName = ?
strParentName = ?
strSonName = ?
Thank you
Related
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
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.
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
I'm using the below to search for a node named "Archive" and then change its colour to red and image index.
Dim d As String = "Archive"
For i = 0 To tvProgress.Nodes.Count - 1
If tvProgress.Nodes(i).Text = d Then
tvProgress.Nodes(i).ForeColor = Color.Red
tvProgress.Nodes(i).ImageIndex = 1
End If
Next
As you see from the below image the node "Archive" has some structure underneath. I would also like to change the colour and image index of these as well. These are not a static node name like "Archive" so I can't simply repeat the process.
There are also other nodes in the treeview that need to be left as the default Blue Folder, Black Text
Is this possible?
You should be able to use this code, just set d to the node you want to search for, and p to anything you want to preserve.
'This stores every node in the TreeView
Dim allNodes As New List(Of TreeNode)
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'the node you want to search for
Dim d As String = "Archive"
'the node you want to preserve
Dim p As String = "Preserve"
CallRecursive(TreeView1)
For Each n As TreeNode In allNodes
If n.Text = d Then
n.ForeColor = Color.Red
n.ImageIndex = 1
ElseIf Not n.Text = p Then
Dim path As String = n.FullPath
Dim l As List(Of String) = path.Split("\").ToList()
If l.Contains(d) Then
If l.IndexOf(n.Text) > l.IndexOf(d) Then
n.ForeColor = Color.Red
n.ImageIndex = 1
End If
End If
End If
Next
End Sub
Private Sub GetRecursive(ByVal n As TreeNode)
allNodes.Add(n)
Dim aNode As TreeNode
For Each aNode In n.Nodes
GetRecursive(aNode)
Next
End Sub
Private Sub CallRecursive(ByVal aTreeView As Windows.Forms.TreeView)
allNodes.Clear()
Dim n As TreeNode
For Each n In aTreeView.Nodes
GetRecursive(n)
Next
End Sub
The procedure used to get every node in the TreeView is called recursive procedure, which basically means that GetRecursive() will call itself until it has been through every node in your TreeView. Thanks to this, this code will go through any TreeView, regardless of depth.
This is the TreeView I used to test this code, before the code is run:
And after the code is run:
I hope this helps, any problems and I will try and help.
Edit:
If you just want to format all nodes under "Archive", use this slightly modified code:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'the node you want to search for
Dim d As String = "Archive"
CallRecursive(TreeView1)
For Each n As TreeNode In allNodes
If n.Text = d Then
n.ForeColor = Color.Red
n.ImageIndex = 1
Else
Dim path As String = n.FullPath
Dim l As List(Of String) = path.Split("\").ToList()
If l.Contains(d) Then
If l.IndexOf(n.Text) > l.IndexOf(d) Then
n.ForeColor = Color.Red
n.ImageIndex = 1
End If
End If
End If
Next
End Sub
Private Sub GetRecursive(ByVal n As TreeNode)
allNodes.Add(n)
Dim aNode As TreeNode
For Each aNode In n.Nodes
GetRecursive(aNode)
Next
End Sub
Private Sub CallRecursive(ByVal aTreeView As Windows.Forms.TreeView)
allNodes.Clear()
Dim n As TreeNode
For Each n In aTreeView.Nodes
GetRecursive(n)
Next
End Sub
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.