janmarini
asked on
TreeView: How to return to selected node
Hi,
I am working with a VB.net application and am implementing a treeview control to load other forms. The form that contains the control populates the treeview from a DB table on the form load event, and all the nodes are collapsed (by default). This is fine for the first time the form is loaded, but I need a way to return to it's previous state (showing the selected node) when the user selects 'back' from the form that was loaded from the selected node. Can this be done?
Thanks,
Jan
put the property "FullPath" of all expanded nodes into a collection or array.
put the "FullPath" of the selected node in a string variable.
while populating the treeview a second time, create the node and check if its "FullPath" is in the collection. if so, expand that node.
when finished get the node whichs "FullPath" you stored in the string variable and set its "Selected"-Property to true.
holli
put the "FullPath" of the selected node in a string variable.
while populating the treeview a second time, create the node and check if its "FullPath" is in the collection. if so, expand that node.
when finished get the node whichs "FullPath" you stored in the string variable and set its "Selected"-Property to true.
holli
ASKER
Thanks for your help both of you.
I've been trying all day to try to get either solution to work for me, but haven't yet been successfull. With the first solution I am having trouble with the statement - AddHandler f2[replaced w/ my form].frmBack, AddressOf backEvent_frmBack - specifically the 'AddressOf backEvent_frmBack' part, something to do with the object (it was a while back and I don't recall the specific error message). Also, when trying this out I think I may have over-simplified my original request (didn't want to scare folks away :-), my app is pretty complex and will either call a new form or load a report in the Crystal Report Viewer - my mention of a 'back' button was for an example - thought if I could figure out how to do that, the rest would follow. Not happening yet.
I had trouble with the second recommendation as well. Do you have a code snippet that might point me in the right direction? I tried a few things and couldn't get it to work. I may just need a fresh perspective, I've been at this since 4AM - and I am facing an urgent need to implement the tree control in my application. (Funny how things always seem to be needed yesterday after months of inactivity).
The worst part is is that I am a newbie with the VB.net version of the TreeView control, so everything is new and nothing has been accomplished with ease ::sigh::
I thought I would simplify my task by storing the Selected.Node into a global variable, then when the primary form re-loads to find that node and re-select it. However, I am now stuck on the recursion - can't get things to go further than the first level of nodes. Any advice here would be greatly appreciated - I'll even open up a new topic and award 500 points separately because I know that there will be others who are struggling with this situation as well, I searched high and low for the answers - but VB.net solutions are scarce (even after 3+ years!), and the VB.6 solutions are misleading (LOL - sometimes I really miss that ol' VB 6).
Dim testnode As TreeNode = TreeView1.Nodes(0)
For Each newNode In testnode.Nodes
If Trim(newNode.Text) = "THE TEXT OF THE NODE" Then TreeView1.SelectedNode = newNode
Next
**Need to figure out how to include the children/grandchildren these nodes might have**
For the full picture, my primary form load code thus far is :
NOTES: (builds the treeview from SQL Server DB) (FYI: walkthrough code not yet cleaned up)
#Region "Form Events"
Private Sub frmSwitchboard_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Try
'set up TreeView
Dim root As TreeNodeCollection = TreeView1.Nodes
Dim newNode As TreeNode
Dim ParentID As Integer
Dim prevParentID As Integer
Dim i, j, k As Integer '***Clean up for final
root.Clear()
'Get Data and populate TreeView
Dim sqlstatement As String
Dim a, b, c, d, f '***step debug - eliminate in final version
sqlstatement = "SELECT * FROM ReportNodes WHERE ParentID = 0 ORDER BY ID, SequenceID"
Dim strTemp As String = ""
strTemp = GetConnectionString("Asses sor")
Dim sqlConn As SqlConnection = New SqlConnection(strTemp)
sqlConn.Open()
Dim cmdSQL As SqlCommand = New SqlCommand(sqlstatement, sqlConn)
Dim dr As SqlDataReader = cmdSQL.ExecuteReader()
Do While dr.Read
newNode = TreeView1.Nodes.Add(dr.Ite m(1)) 'Add Parent to root
newNode.ImageIndex = 0
'Get Children
sqlstatement = "SELECT * FROM ReportNodes WHERE ParentID = " & (dr.Item(0)) & " ORDER BY NodeLevel, SequenceID"
sqlDS.Clear()
GetDataSet(sqlstatement, "Assessor", "Children")
Dim tbl As DataTable = sqlDS.Tables("Children")
Dim row As DataRow = tbl.Rows(0)
row = tbl.Rows(0)
a = tbl.Rows.Count
For i = 0 To tbl.Rows.Count - 1
row = tbl.Rows(i)
a = row("NodeName")
If i > 0 And row("NodeLevel") > 0 Then
newNode = newNode.Parent.Parent
newNode = newNode.Nodes.Add(row("Nod eName"))
Else
If row("NodeLevel") > 0 Then
newNode = newNode.Nodes.Add(row("Nod eName"))
Else
newNode.Nodes.Add(row("Nod eName"))
End If
End If
sqlstatement = "SELECT * FROM ReportNodes WHERE ParentID = " & (row("ID")) & " ORDER BY NodeLevel, SequenceID"
GetDataSet(sqlstatement, "Assessor", "Child")
Dim tbl2 As DataTable = sqlDS.Tables("Child")
If tbl2.Rows.Count > 0 Then
Dim row2 As DataRow = tbl2.Rows(0)
row2 = tbl2.Rows(0)
For j = 0 To tbl2.Rows.Count - 1
row2 = tbl2.Rows(j)
a = row2("NodeName")
b = row2("NodeLevel")
If j > 0 Then
newNode = newNode.Parent
newNode = newNode.Nodes.Add(row2("No deName"))
Else
newNode = newNode.Nodes.Add(row2("No deName"))
End If
sqlstatement = "SELECT * FROM ReportNodes WHERE ParentID = " & (row2("ID")) & " ORDER BY NodeLevel, SequenceID"
GetDataSet(sqlstatement, "Assessor", "GrandChildren")
Dim tbl3 As DataTable = sqlDS.Tables("GrandChildre n")
If tbl3.Rows.Count > 0 Then
Dim row3 As DataRow = tbl3.Rows(0)
row3 = tbl3.Rows(0)
For k = 0 To tbl3.Rows.Count - 1
row3 = tbl3.Rows(k)
a = row3("NodeName")
b = row3("NodeLevel")
newNode.Nodes.Add(row3("No deName"))
Next k
sqlDS.Tables("GrandChildre n").Clear( )
End If
Next j
End If
sqlDS.Tables("Child").Clea r()
sqlDS.Tables("GrandChildre n").Clear( )
Next i
Loop
dr.Close()
'***HERE IS WHERE I WOULD LIKE TO LEARN HOW TO GET TO THE SUBORDINATE NODES
Dim testnode As TreeNode = TreeView1.Nodes(0)
For Each newNode In testnode.Nodes
If Trim(newNode.Text) = "THE TEXT OF THE NODE" Then TreeView1.SelectedNode = newNode
Next
'***
Catch ex As System.Exception
MessageBox.Show(ex.Message , "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
Finally
End Try
End Sub
#End Region
Private Sub TreeView1_AfterSelect(ByVa l sender As System.Object, _
ByVal e As System.Windows.Forms.TreeV iewEventAr gs) Handles TreeView1.AfterSelect
' Determine by checking Text property.
'MessageBox.Show("AfterSel ect" & e.Node.Text & " " & e.Node.Index)
Try
Select Case Trim(TreeView1.SelectedNod e.Text
.
.
.
Case "A-3b. Apartment Complexes"
glbReport = "SA_ER_APT"
Dim frm As New frmReportEngine()
Me.Hide()
frm.ShowDialog()
Case Else
End Select
'***HERE IS WHERE I TRIED STORING THE SELECTED NODE TO BE USED LATER
'glbSelectedNode = TreeView1.SelectedNode
'b = TreeView1.SelectedNode.Tex t
'***
Catch ex As System.Exception
MessageBox.Show(ex.Message , "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
Finally
End Try
End Sub
I've been trying all day to try to get either solution to work for me, but haven't yet been successfull. With the first solution I am having trouble with the statement - AddHandler f2[replaced w/ my form].frmBack, AddressOf backEvent_frmBack - specifically the 'AddressOf backEvent_frmBack' part, something to do with the object (it was a while back and I don't recall the specific error message). Also, when trying this out I think I may have over-simplified my original request (didn't want to scare folks away :-), my app is pretty complex and will either call a new form or load a report in the Crystal Report Viewer - my mention of a 'back' button was for an example - thought if I could figure out how to do that, the rest would follow. Not happening yet.
I had trouble with the second recommendation as well. Do you have a code snippet that might point me in the right direction? I tried a few things and couldn't get it to work. I may just need a fresh perspective, I've been at this since 4AM - and I am facing an urgent need to implement the tree control in my application. (Funny how things always seem to be needed yesterday after months of inactivity).
The worst part is is that I am a newbie with the VB.net version of the TreeView control, so everything is new and nothing has been accomplished with ease ::sigh::
I thought I would simplify my task by storing the Selected.Node into a global variable, then when the primary form re-loads to find that node and re-select it. However, I am now stuck on the recursion - can't get things to go further than the first level of nodes. Any advice here would be greatly appreciated - I'll even open up a new topic and award 500 points separately because I know that there will be others who are struggling with this situation as well, I searched high and low for the answers - but VB.net solutions are scarce (even after 3+ years!), and the VB.6 solutions are misleading (LOL - sometimes I really miss that ol' VB 6).
Dim testnode As TreeNode = TreeView1.Nodes(0)
For Each newNode In testnode.Nodes
If Trim(newNode.Text) = "THE TEXT OF THE NODE" Then TreeView1.SelectedNode = newNode
Next
**Need to figure out how to include the children/grandchildren these nodes might have**
For the full picture, my primary form load code thus far is :
NOTES: (builds the treeview from SQL Server DB) (FYI: walkthrough code not yet cleaned up)
#Region "Form Events"
Private Sub frmSwitchboard_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Try
'set up TreeView
Dim root As TreeNodeCollection = TreeView1.Nodes
Dim newNode As TreeNode
Dim ParentID As Integer
Dim prevParentID As Integer
Dim i, j, k As Integer '***Clean up for final
root.Clear()
'Get Data and populate TreeView
Dim sqlstatement As String
Dim a, b, c, d, f '***step debug - eliminate in final version
sqlstatement = "SELECT * FROM ReportNodes WHERE ParentID = 0 ORDER BY ID, SequenceID"
Dim strTemp As String = ""
strTemp = GetConnectionString("Asses
Dim sqlConn As SqlConnection = New SqlConnection(strTemp)
sqlConn.Open()
Dim cmdSQL As SqlCommand = New SqlCommand(sqlstatement, sqlConn)
Dim dr As SqlDataReader = cmdSQL.ExecuteReader()
Do While dr.Read
newNode = TreeView1.Nodes.Add(dr.Ite
newNode.ImageIndex = 0
'Get Children
sqlstatement = "SELECT * FROM ReportNodes WHERE ParentID = " & (dr.Item(0)) & " ORDER BY NodeLevel, SequenceID"
sqlDS.Clear()
GetDataSet(sqlstatement, "Assessor", "Children")
Dim tbl As DataTable = sqlDS.Tables("Children")
Dim row As DataRow = tbl.Rows(0)
row = tbl.Rows(0)
a = tbl.Rows.Count
For i = 0 To tbl.Rows.Count - 1
row = tbl.Rows(i)
a = row("NodeName")
If i > 0 And row("NodeLevel") > 0 Then
newNode = newNode.Parent.Parent
newNode = newNode.Nodes.Add(row("Nod
Else
If row("NodeLevel") > 0 Then
newNode = newNode.Nodes.Add(row("Nod
Else
newNode.Nodes.Add(row("Nod
End If
End If
sqlstatement = "SELECT * FROM ReportNodes WHERE ParentID = " & (row("ID")) & " ORDER BY NodeLevel, SequenceID"
GetDataSet(sqlstatement, "Assessor", "Child")
Dim tbl2 As DataTable = sqlDS.Tables("Child")
If tbl2.Rows.Count > 0 Then
Dim row2 As DataRow = tbl2.Rows(0)
row2 = tbl2.Rows(0)
For j = 0 To tbl2.Rows.Count - 1
row2 = tbl2.Rows(j)
a = row2("NodeName")
b = row2("NodeLevel")
If j > 0 Then
newNode = newNode.Parent
newNode = newNode.Nodes.Add(row2("No
Else
newNode = newNode.Nodes.Add(row2("No
End If
sqlstatement = "SELECT * FROM ReportNodes WHERE ParentID = " & (row2("ID")) & " ORDER BY NodeLevel, SequenceID"
GetDataSet(sqlstatement, "Assessor", "GrandChildren")
Dim tbl3 As DataTable = sqlDS.Tables("GrandChildre
If tbl3.Rows.Count > 0 Then
Dim row3 As DataRow = tbl3.Rows(0)
row3 = tbl3.Rows(0)
For k = 0 To tbl3.Rows.Count - 1
row3 = tbl3.Rows(k)
a = row3("NodeName")
b = row3("NodeLevel")
newNode.Nodes.Add(row3("No
Next k
sqlDS.Tables("GrandChildre
End If
Next j
End If
sqlDS.Tables("Child").Clea
sqlDS.Tables("GrandChildre
Next i
Loop
dr.Close()
'***HERE IS WHERE I WOULD LIKE TO LEARN HOW TO GET TO THE SUBORDINATE NODES
Dim testnode As TreeNode = TreeView1.Nodes(0)
For Each newNode In testnode.Nodes
If Trim(newNode.Text) = "THE TEXT OF THE NODE" Then TreeView1.SelectedNode = newNode
Next
'***
Catch ex As System.Exception
MessageBox.Show(ex.Message
Finally
End Try
End Sub
#End Region
Private Sub TreeView1_AfterSelect(ByVa
ByVal e As System.Windows.Forms.TreeV
' Determine by checking Text property.
'MessageBox.Show("AfterSel
Try
Select Case Trim(TreeView1.SelectedNod
.
.
.
Case "A-3b. Apartment Complexes"
glbReport = "SA_ER_APT"
Dim frm As New frmReportEngine()
Me.Hide()
frm.ShowDialog()
Case Else
End Select
'***HERE IS WHERE I TRIED STORING THE SELECTED NODE TO BE USED LATER
'glbSelectedNode = TreeView1.SelectedNode
'b = TreeView1.SelectedNode.Tex
'***
Catch ex As System.Exception
MessageBox.Show(ex.Message
Finally
End Try
End Sub
In this line:
AddHandler f2.frmBack, AddressOf backEvent_frmBack
you are correct in replacing f2 with your form name. frmBack is the name of the event you have declared that each form must declare. The AddressOf part points to the name of the subroutine that will handle the event, usually in the same class (but not necessarily). It must have the same parameter signature as the event you are handling.
~IM
AddHandler f2.frmBack, AddressOf backEvent_frmBack
you are correct in replacing f2 with your form name. frmBack is the name of the event you have declared that each form must declare. The AddressOf part points to the name of the subroutine that will handle the event, usually in the same class (but not necessarily). It must have the same parameter signature as the event you are handling.
~IM
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thanks Holli,
Your solution worked perfectly. It is such a relief to have this done! I really appreciate your help.
Thanks also IM, although I didn't get a chance to further explore your solution after I got things to work, it is really good to know that there are alternatives. I am sure this is going to help someone in the future. I wish I could award you some points too!
Your solution worked perfectly. It is such a relief to have this done! I really appreciate your help.
Thanks also IM, although I didn't get a chance to further explore your solution after I got things to work, it is really good to know that there are alternatives. I am sure this is going to help someone in the future. I wish I could award you some points too!
What you can do is store the selected node in the tag property of the form that is opened. Then when the "back" button is pushed, you can raise a custom event that will pass the selected node back to the main form.
Something like this:
' --------------------------
' Secondary Form opened from TreeView
' --------------------------
Public Class Form2
Inherits System.Windows.Forms.Form
Public Event frmBack(ByVal selectedNode As TreeNode) ' <--- Your custom "back" event
Private Sub btnBack_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnBack.Click
If Not (Me.Tag Is Nothing) Then
RaiseEvent frmBack(Me.Tag) ' <--- raise the event, passing the selected node back to the main form
Me.Close()
End If
End Sub
End Class
' --------------------------
' Main Form with TreeView
' --------------------------
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
' open the appropriate form...however you do it
Dim f2 As New Form2
f2.Tag = TreeView1.SelectedNode ' <--- put the selected node in the new forms tag property
AddHandler f2.frmBack, AddressOf backEvent_frmBack ' <--- Add a handler so we can trap the "back" button event
f2.Show()
End Sub
Private Sub backEvent_frmBack(ByVal selectedNode As System.Windows.Forms.TreeN
' one of the "back" buttons has been pushed
' make the node passed back in the current one and expand it
TreeView1.SelectedNode = selectedNode
TreeView1.SelectedNode.Exp
End Sub