Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. Visual Basic
  4. TreeView Find Starting from Some Child Node

TreeView Find Starting from Some Child Node

Scheduled Pinned Locked Moved Visual Basic
data-structures
9 Posts 3 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • T Offline
    T Offline
    treddie
    wrote on last edited by
    #1

    Hello. I am having zero luck finding anything on doing a TreeView1.Nodes.Find() starting from a particular child node. Find() apparently works over the entire tree, and does not let you specify a starting point in the tree.

    L 1 Reply Last reply
    0
    • T treddie

      Hello. I am having zero luck finding anything on doing a TreeView1.Nodes.Find() starting from a particular child node. Find() apparently works over the entire tree, and does not let you specify a starting point in the tree.

      L Offline
      L Offline
      Lost User
      wrote on last edited by
      #2

      treddie wrote:

      I am having zero luck finding anything on doing a TreeView1.Nodes.Find() starting from a particular child node.

      Don't trust on luck. Where's your code?

      treddie wrote:

      Find() apparently works over the entire tree, and does not let you specify a starting point in the tree.

      Trying something like below?

      Imports System.Windows.Forms
      Module Module1
      Private TreeView1 As New TreeView()
      Sub Main()
      Using f As New Form
      Dim btn As New Button
      btn.Dock = DockStyle.Top
      Dim node1 As TreeNode = TreeView1.Nodes.Add("Node1")
      node1.Nodes.Add("Sub1", "Sub1").Nodes.Add("Hello", "Hello")
      Dim node2 As TreeNode = TreeView1.Nodes.Add("Node2")
      node2.Nodes.Add("Sub1", "Sub1").Nodes.Add("Hello", "Hello")

              Dim foundNodes As TreeNode() = node2.Nodes.Find("Hello", True)
      
              If foundNodes.Length > 0 Then
                  TreeView1.SelectedNode = foundNodes(0)
                  TreeView1.Focus()
              End If
      
              f.Controls.Add(TreeView1)
              f.Controls.Add(btn)
              f.ShowDialog()
          End Using
      End Sub
      

      End Module

      Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^]

      T 1 Reply Last reply
      0
      • L Lost User

        treddie wrote:

        I am having zero luck finding anything on doing a TreeView1.Nodes.Find() starting from a particular child node.

        Don't trust on luck. Where's your code?

        treddie wrote:

        Find() apparently works over the entire tree, and does not let you specify a starting point in the tree.

        Trying something like below?

        Imports System.Windows.Forms
        Module Module1
        Private TreeView1 As New TreeView()
        Sub Main()
        Using f As New Form
        Dim btn As New Button
        btn.Dock = DockStyle.Top
        Dim node1 As TreeNode = TreeView1.Nodes.Add("Node1")
        node1.Nodes.Add("Sub1", "Sub1").Nodes.Add("Hello", "Hello")
        Dim node2 As TreeNode = TreeView1.Nodes.Add("Node2")
        node2.Nodes.Add("Sub1", "Sub1").Nodes.Add("Hello", "Hello")

                Dim foundNodes As TreeNode() = node2.Nodes.Find("Hello", True)
        
                If foundNodes.Length > 0 Then
                    TreeView1.SelectedNode = foundNodes(0)
                    TreeView1.Focus()
                End If
        
                f.Controls.Add(TreeView1)
                f.Controls.Add(btn)
                f.ShowDialog()
            End Using
        End Sub
        

        End Module

        Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^]

        T Offline
        T Offline
        treddie
        wrote on last edited by
        #3

        Hey, Eddy. I probably should have put this post in my other thread, since I thought I was asking a separate question, but it turns out, I'm back to the old topic! :) The problem I see with that solution is that it assumes that you know that the answer lies somewhere beneath Node2 and not Node1. In fact, if you don't know, then you either have to ' 1). Search the whole tree and find all instances of "Hello", then look at the full path property to see if it matches a pre-defined path, or ' 2). You have to be able to step through each node with Find(), and searchAllChildren = "False", to prevent the search from going any deeper than one node at a time. It also has to reject any instances of the search name that might occur ABOVE the current node. In the latter case, as far as I can tell, you need to be able to set a child node as a current node, as if it was the parent node so that the search starts from there. But vb.Net offers no way to set a child node to "Current" during a Find(). UPDATE: If I change your code to the following:

          Dim MyNodes(2) As TreeNode
        
          MyNodes(1) = TreeView1.Nodes.Add("Node1")
          MyNodes(1).Nodes.Add("Sub1", "Sub1").Nodes.Add("Hello", "Hello")
        
          MyNodes(2) = TreeView1.Nodes.Add("Node2")
          MyNodes(2).Nodes.Add("Sub1", "Sub1").Nodes.Add("Hello", "Hello")
        
          Dim foundNodes As TreeNode() = MyNodes(2).Nodes.Find("Hello", True)
        
          If foundNodes.Length > 0 Then
            TreeView1.SelectedNode = foundNodes(0)
            TreeView1.Focus()
          End If
        

        I gain flexibility in how the parent node is defined, but there is still no flexibility in the Find() operation...If instead of: = MyNodes(2).Nodes.Find("Hello", True) ' I want to do: = MyNodes(2).My1stChildNodes(3).Nodes.Find("Hello", True) I have to set that up explicitly. And it does not seem to be a problem that lends itself to recursion. The only option then, is to set up separate Find() functions for each node depth you want to start at. For a harddrive's directory structure, that could end up being 10-20 separate functions, easily.

        L 1 Reply Last reply
        0
        • T treddie

          Hey, Eddy. I probably should have put this post in my other thread, since I thought I was asking a separate question, but it turns out, I'm back to the old topic! :) The problem I see with that solution is that it assumes that you know that the answer lies somewhere beneath Node2 and not Node1. In fact, if you don't know, then you either have to ' 1). Search the whole tree and find all instances of "Hello", then look at the full path property to see if it matches a pre-defined path, or ' 2). You have to be able to step through each node with Find(), and searchAllChildren = "False", to prevent the search from going any deeper than one node at a time. It also has to reject any instances of the search name that might occur ABOVE the current node. In the latter case, as far as I can tell, you need to be able to set a child node as a current node, as if it was the parent node so that the search starts from there. But vb.Net offers no way to set a child node to "Current" during a Find(). UPDATE: If I change your code to the following:

            Dim MyNodes(2) As TreeNode
          
            MyNodes(1) = TreeView1.Nodes.Add("Node1")
            MyNodes(1).Nodes.Add("Sub1", "Sub1").Nodes.Add("Hello", "Hello")
          
            MyNodes(2) = TreeView1.Nodes.Add("Node2")
            MyNodes(2).Nodes.Add("Sub1", "Sub1").Nodes.Add("Hello", "Hello")
          
            Dim foundNodes As TreeNode() = MyNodes(2).Nodes.Find("Hello", True)
          
            If foundNodes.Length > 0 Then
              TreeView1.SelectedNode = foundNodes(0)
              TreeView1.Focus()
            End If
          

          I gain flexibility in how the parent node is defined, but there is still no flexibility in the Find() operation...If instead of: = MyNodes(2).Nodes.Find("Hello", True) ' I want to do: = MyNodes(2).My1stChildNodes(3).Nodes.Find("Hello", True) I have to set that up explicitly. And it does not seem to be a problem that lends itself to recursion. The only option then, is to set up separate Find() functions for each node depth you want to start at. For a harddrive's directory structure, that could end up being 10-20 separate functions, easily.

          L Offline
          L Offline
          Lost User
          wrote on last edited by
          #4

          treddie wrote:

          is that it assumes that you know that the answer lies somewhere beneath Node2 and not Node1. In fact, if you don't know, then you either have to

          If it's a path, then you'll know where it's located. If it's a random property, you'll have to go and check each item.

          treddie wrote:

          I want to do:
          = MyNodes(2).My1stChildNodes(3).Nodes.Find("Hello", True)

          TreeView1.Nodes("Node2").Nodes("Sub1").Nodes.Find("Hello")

          What are you trying to do? This way of solving does not seem to be very helpful/fruitfull :)

          Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^]

          T 1 Reply Last reply
          0
          • L Lost User

            treddie wrote:

            is that it assumes that you know that the answer lies somewhere beneath Node2 and not Node1. In fact, if you don't know, then you either have to

            If it's a path, then you'll know where it's located. If it's a random property, you'll have to go and check each item.

            treddie wrote:

            I want to do:
            = MyNodes(2).My1stChildNodes(3).Nodes.Find("Hello", True)

            TreeView1.Nodes("Node2").Nodes("Sub1").Nodes.Find("Hello")

            What are you trying to do? This way of solving does not seem to be very helpful/fruitfull :)

            Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^]

            T Offline
            T Offline
            treddie
            wrote on last edited by
            #5

            The basic problem is this. In vb6 (and the COM controls as they were carried over into .Net), you have Dir and File List boxes. You could double-click a folder or file name and do something with it. You can do the same thing with a TreeView. The problem starts when you want to save out those selections when you close the program, so that when you come back, the Treeview has the old selections intact. That was no problem with a Dir or file Listbox, because you could simply set the boxes to a desired path name. The question that comes up might be, "Well, why not stick to using Dir and File ListBoxes, then?" I wanted to do just that to simplify my port-over to vb.Net, and that would have been fine...If not for the fact that Dir/File Listboxes cannot pass the MAX_PATH = 260 barrier. Another problem in vb6, is that the ListBoxes are not Unicode compatible. But even though they are in .Net, the MAX_PATH barrier is still insurmountable. So, the TreeView is the "only" answer. But there is no way to tell a TreeView to select a given node based either on a fullpath (there is no option for this), or to tell it to go to a particular node index or node handle. The only option is to store the node sequence (like, "1, 3, 2, 7") and count how many child nodes that translates into (4), then go to a sub or function that explicitly utilizes that same amount of nodes, (Nodes(1).Nodes(3),Nodes(2).Nodes(7)) in one or more methods. Now, in my 1/2 hour quick check of folder depths on my c:\ drive, I counted a maximum folder depth of 12, so it could easily be over that amount. That means, bare minimum, I would need 12 separate subs (These are quicky examples, and not debugged):

            Private Sub 1Node (ByVal ChildNodes() as Integer)
            TreeView1.SelectedNode = TreeView1.Nodes(x)
            TreeView1.SelectedNode.Expand()
            End Sub

            Private Sub 2Nodes (ByVal ChildNodes() as Integer)
            TreeView1.SelectedNode = TreeView1.Nodes(x).Nodes(y)
            TreeView1.SelectedNode.Expand()
            End Sub

            Private Sub 3Nodes (ByVal ChildNodes() as Integer)
            TreeView1.SelectedNode = TreeView1.Nodes(x).Nodes(y).Nodes(z)
            TreeView1.SelectedNode.Expand()
            End Sub

            And on and on for at LEAST 12 subs. Now, you just know many people will have folder depths much larger than that (And my drives might, too), so where do you stop? 20 subs? 30 subs? 100 Subs?! I would think to be on the safe side and throwing in a safety factor of 3, a bare minimum of 60 Subs. That is hardly elegant, but if that is what I need to do, then that is just the

            T L 2 Replies Last reply
            0
            • T treddie

              The basic problem is this. In vb6 (and the COM controls as they were carried over into .Net), you have Dir and File List boxes. You could double-click a folder or file name and do something with it. You can do the same thing with a TreeView. The problem starts when you want to save out those selections when you close the program, so that when you come back, the Treeview has the old selections intact. That was no problem with a Dir or file Listbox, because you could simply set the boxes to a desired path name. The question that comes up might be, "Well, why not stick to using Dir and File ListBoxes, then?" I wanted to do just that to simplify my port-over to vb.Net, and that would have been fine...If not for the fact that Dir/File Listboxes cannot pass the MAX_PATH = 260 barrier. Another problem in vb6, is that the ListBoxes are not Unicode compatible. But even though they are in .Net, the MAX_PATH barrier is still insurmountable. So, the TreeView is the "only" answer. But there is no way to tell a TreeView to select a given node based either on a fullpath (there is no option for this), or to tell it to go to a particular node index or node handle. The only option is to store the node sequence (like, "1, 3, 2, 7") and count how many child nodes that translates into (4), then go to a sub or function that explicitly utilizes that same amount of nodes, (Nodes(1).Nodes(3),Nodes(2).Nodes(7)) in one or more methods. Now, in my 1/2 hour quick check of folder depths on my c:\ drive, I counted a maximum folder depth of 12, so it could easily be over that amount. That means, bare minimum, I would need 12 separate subs (These are quicky examples, and not debugged):

              Private Sub 1Node (ByVal ChildNodes() as Integer)
              TreeView1.SelectedNode = TreeView1.Nodes(x)
              TreeView1.SelectedNode.Expand()
              End Sub

              Private Sub 2Nodes (ByVal ChildNodes() as Integer)
              TreeView1.SelectedNode = TreeView1.Nodes(x).Nodes(y)
              TreeView1.SelectedNode.Expand()
              End Sub

              Private Sub 3Nodes (ByVal ChildNodes() as Integer)
              TreeView1.SelectedNode = TreeView1.Nodes(x).Nodes(y).Nodes(z)
              TreeView1.SelectedNode.Expand()
              End Sub

              And on and on for at LEAST 12 subs. Now, you just know many people will have folder depths much larger than that (And my drives might, too), so where do you stop? 20 subs? 30 subs? 100 Subs?! I would think to be on the safe side and throwing in a safety factor of 3, a bare minimum of 60 Subs. That is hardly elegant, but if that is what I need to do, then that is just the

              T Offline
              T Offline
              TnTinMn
              wrote on last edited by
              #6

              ..... But there is no way to tell a TreeView to select a given node based either on a fullpath (there is no option for this)

              So what is preventing you from writing a routine to do this? It is not that hard.

              Private Function NodeFromPath(ByVal path As String, ByVal tv As TreeView) As TreeNode
              NodeFromPath = Nothing
              Dim parts() As String = path.Split(New String() {tv.PathSeparator}, StringSplitOptions.None)
              Dim nodes As TreeNodeCollection
              nodes = tv.Nodes
              Dim found() As TreeNode
              For Each part As String In parts
              found = nodes.Find(part, False)
              If found.Length = 0 Then
              Return Nothing
              Else
              NodeFromPath = found(0)
              nodes = NodeFromPath.Nodes
              End If
              Next
              End Function

              T 1 Reply Last reply
              0
              • T TnTinMn

                ..... But there is no way to tell a TreeView to select a given node based either on a fullpath (there is no option for this)

                So what is preventing you from writing a routine to do this? It is not that hard.

                Private Function NodeFromPath(ByVal path As String, ByVal tv As TreeView) As TreeNode
                NodeFromPath = Nothing
                Dim parts() As String = path.Split(New String() {tv.PathSeparator}, StringSplitOptions.None)
                Dim nodes As TreeNodeCollection
                nodes = tv.Nodes
                Dim found() As TreeNode
                For Each part As String In parts
                found = nodes.Find(part, False)
                If found.Length = 0 Then
                Return Nothing
                Else
                NodeFromPath = found(0)
                nodes = NodeFromPath.Nodes
                End If
                Next
                End Function

                T Offline
                T Offline
                treddie
                wrote on last edited by
                #7

                JEEZ! That's exactly what I was trying to do! I could not find any references to anything like NodeFromPath, which would have been a huge timesaver there, alone! And with my relative newness to vb.Net, don't think I would have discovered the syntax you used for "Dim parts()" for a very long, long time. I must confess this one had my head all fouled up. :doh: :omg: :wtf: Sorry, I could not find an emoticon for red-faced.

                1 Reply Last reply
                0
                • T treddie

                  The basic problem is this. In vb6 (and the COM controls as they were carried over into .Net), you have Dir and File List boxes. You could double-click a folder or file name and do something with it. You can do the same thing with a TreeView. The problem starts when you want to save out those selections when you close the program, so that when you come back, the Treeview has the old selections intact. That was no problem with a Dir or file Listbox, because you could simply set the boxes to a desired path name. The question that comes up might be, "Well, why not stick to using Dir and File ListBoxes, then?" I wanted to do just that to simplify my port-over to vb.Net, and that would have been fine...If not for the fact that Dir/File Listboxes cannot pass the MAX_PATH = 260 barrier. Another problem in vb6, is that the ListBoxes are not Unicode compatible. But even though they are in .Net, the MAX_PATH barrier is still insurmountable. So, the TreeView is the "only" answer. But there is no way to tell a TreeView to select a given node based either on a fullpath (there is no option for this), or to tell it to go to a particular node index or node handle. The only option is to store the node sequence (like, "1, 3, 2, 7") and count how many child nodes that translates into (4), then go to a sub or function that explicitly utilizes that same amount of nodes, (Nodes(1).Nodes(3),Nodes(2).Nodes(7)) in one or more methods. Now, in my 1/2 hour quick check of folder depths on my c:\ drive, I counted a maximum folder depth of 12, so it could easily be over that amount. That means, bare minimum, I would need 12 separate subs (These are quicky examples, and not debugged):

                  Private Sub 1Node (ByVal ChildNodes() as Integer)
                  TreeView1.SelectedNode = TreeView1.Nodes(x)
                  TreeView1.SelectedNode.Expand()
                  End Sub

                  Private Sub 2Nodes (ByVal ChildNodes() as Integer)
                  TreeView1.SelectedNode = TreeView1.Nodes(x).Nodes(y)
                  TreeView1.SelectedNode.Expand()
                  End Sub

                  Private Sub 3Nodes (ByVal ChildNodes() as Integer)
                  TreeView1.SelectedNode = TreeView1.Nodes(x).Nodes(y).Nodes(z)
                  TreeView1.SelectedNode.Expand()
                  End Sub

                  And on and on for at LEAST 12 subs. Now, you just know many people will have folder depths much larger than that (And my drives might, too), so where do you stop? 20 subs? 30 subs? 100 Subs?! I would think to be on the safe side and throwing in a safety factor of 3, a bare minimum of 60 Subs. That is hardly elegant, but if that is what I need to do, then that is just the

                  L Offline
                  L Offline
                  Lost User
                  wrote on last edited by
                  #8

                  treddie wrote:

                  So, the TreeView is the "only" answer.

                  Search CP, and you'll find that a lot of people think something similar.

                  treddie wrote:

                  so where do you stop?

                  The moment I recognize the repeating pattern; same code, same handler, just a different level. Neat piece o' code that TnTinMan posted, mine would have been longer :)

                  Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^]

                  T 1 Reply Last reply
                  0
                  • L Lost User

                    treddie wrote:

                    So, the TreeView is the "only" answer.

                    Search CP, and you'll find that a lot of people think something similar.

                    treddie wrote:

                    so where do you stop?

                    The moment I recognize the repeating pattern; same code, same handler, just a different level. Neat piece o' code that TnTinMan posted, mine would have been longer :)

                    Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^]

                    T Offline
                    T Offline
                    treddie
                    wrote on last edited by
                    #9

                    Eddy Vluggen wrote:

                    Search CP, and you'll find that a lot of people think something similar.

                    Well, at least I'm not alone.

                    Eddy Vluggen wrote:

                    The moment I recognize the repeating pattern; same code, same handler, just a different level. Neat piece o' code that TnTinMan posted, mine would have been longer

                    Problem is I couldn't find a way to generalize the repeating code. I looked all over for something to do just that and continued to try to solve it, but my unfamiliarity with the TreeView properties bit my ass. That really is a nice compact piece of code. After looking at it, it seems that what makes it work, is that once each match is made, what is important is the handle of the node. Otherwise, since two nodes can have the same name and text label, there would be no way for vb to know what node was being referred to. But the handles are all different. I tried working with the handles earlier, but could not find a way to get a node selected based on its handle.

                    1 Reply Last reply
                    0
                    Reply
                    • Reply as topic
                    Log in to reply
                    • Oldest to Newest
                    • Newest to Oldest
                    • Most Votes


                    • Login

                    • Don't have an account? Register

                    • Login or register to search.
                    • First post
                      Last post
                    0
                    • Categories
                    • Recent
                    • Tags
                    • Popular
                    • World
                    • Users
                    • Groups