vb.netlistviewtreeview

In VB.Net, navigate to Treeview node based on filepath


In my Windows Explorer type app with the obligatory Treeview and Listview, and having the users chosen file path continually updating in a Textbox, is there a way to navigate to different nodes in the Treeview using the actual file path directly? The Text and Tag of each node is the same. This would be useful for instance, to duplicate Explorer's "Up" button among other things, but I cant seem to find any information on it other than lengthy looping processes. Any suggestions would be appreciated.

This is the code I have tried:

Imports System.IO
Public Class Form1
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        TreeView1.HideSelection = False
        For Each Drive In DriveInfo.GetDrives
            If (Drive.IsReady) Then
                Dim dName As String = Drive.VolumeLabel
                If String.IsNullOrEmpty(dName) Then
                    dName = Drive.Name
                End If

                Dim tNode As New TreeNode()

                With tNode
                    .ImageIndex = 0
                    .SelectedImageIndex = 0
                    .Text = dName
                    .Nodes.Add("")
                    .Tag = dName
                End With
                TreeView1.Nodes.Add(tNode)
            End If
        Next

        'Dim TreeNode1 As TreeNode = New TreeNode("Private")
        'Dim TreeNode2 As TreeNode = New TreeNode("Public")
        'Dim TreeNode3 As TreeNode = New TreeNode("Data", New TreeNode() {TreeNode1, TreeNode2})
        'Dim TreeNode4 As TreeNode = New TreeNode("Pictures")
        'Dim TreeNode5 As TreeNode = New TreeNode("C:", New TreeNode() {TreeNode3, TreeNode4})

        'TreeView1.HideSelection = False
        'TreeView1.Name = "TreeView1"
        'TreeNode1.Name = "C:\Data\Private"
        'TreeNode1.Text = "Private"
        'TreeNode2.Name = "C:\Data\Public"
        'TreeNode2.Text = "Public"
        'TreeNode3.Name = "C:\Data"
        'TreeNode3.Text = "Data"
        'TreeNode4.Name = "C:\Pictures"
        'TreeNode4.Text = "Pictures"
        'TreeNode5.Name = "C:"
        'TreeNode5.Text = "C:"
        'TreeView1.Nodes.AddRange(New TreeNode() {TreeNode5})

    End Sub

    Private Sub TreeView1_BeforeExpand(sender As Object, e As TreeViewCancelEventArgs) Handles TreeView1.BeforeExpand
        GetFolders(e.Node)
    End Sub

    Private Sub GetFolders(ByVal PathName As TreeNode)
        Dim di As DirectoryInfo
        PathName.Nodes.Clear()
        di = New DirectoryInfo(PathName.Tag)

        Try
            For Each nFolder In di.GetDirectories()
                Dim tNode As New TreeNode()

                With tNode
                    .ImageIndex = 1
                    .SelectedImageIndex = 1
                    .Tag = nFolder.FullName
                    .Text = nFolder.Name.ToString()
                    .Nodes.Add("")
                End With

                di = New DirectoryInfo(tNode.Tag)

                If (di.Attributes And FileAttributes.Hidden) = False Then
                    PathName.Nodes.Add(tNode)
                End If

            Next
        Catch ex As Exception
        End Try
    End Sub

    Private Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged
        Dim nodes As TreeNode() = TreeView1.Nodes.Find(TextBox1.Text, True)
        If nodes.Length > 0 Then
            Dim selectedNode As TreeNode = nodes(0)
            TreeView1.SelectedNode = selectedNode
            selectedNode.Expand()
            selectedNode.EnsureVisible()
        End If
    End Sub
End Class

If I just run your code, it works fine. Mine however, loading the file structure doesn't "Find"


Solution

  • There is a Find method in the TreeNodeCollection. It returns an array of found nodes matching the Name property of a node.

    I have set up a little test Form in the Forms designer (excerpt from Form1.Designer.vb):

    Private Sub InitializeComponent()
        Dim TreeNode1 As TreeNode = New TreeNode("Private")
        Dim TreeNode2 As TreeNode = New TreeNode("Public")
        Dim TreeNode3 As TreeNode = New TreeNode("Data", New TreeNode() {TreeNode1, TreeNode2})
        Dim TreeNode4 As TreeNode = New TreeNode("Pictures")
        Dim TreeNode5 As TreeNode = New TreeNode("C:", New TreeNode() {TreeNode3, TreeNode4})
        TreeView1 = New TreeView()
        TextBox1 = New TextBox()
        SuspendLayout()
        '
        ' TreeView1
        ' 
        TreeView1.HideSelection = False
        TreeView1.Location = New Point(55, 213)
        TreeView1.Name = "TreeView1"
        TreeNode1.Name = "C:\Data\Private"
        TreeNode1.Text = "Private"
        TreeNode2.Name = "C:\Data\Public"
        TreeNode2.Text = "Public"
        TreeNode3.Name = "C:\Data"
        TreeNode3.Text = "Data"
        TreeNode4.Name = "C:\Pictures"
        TreeNode4.Text = "Pictures"
        TreeNode5.Name = "C:"
        TreeNode5.Text = "C:"
        TreeView1.Nodes.AddRange(New TreeNode() {TreeNode5})
        TreeView1.Size = New Size(262, 144)
        TreeView1.TabIndex = 3
        ' 
        ' TextBox1
        ' 
        TextBox1.Location = New Point(55, 364)
        TextBox1.Name = "TextBox1"
        TextBox1.Size = New Size(262, 23)
        TextBox1.TabIndex = 4
        ' 
        ' Form1
        ' 
        AutoScaleDimensions = New SizeF(7F, 15F)
        AutoScaleMode = AutoScaleMode.Font
        ClientSize = New Size(800, 450)
        Controls.Add(TextBox1)
        Controls.Add(TreeView1)
        Name = "Form1"
        Text = "Form1"
        ResumeLayout(False)
        PerformLayout()
    End Sub
    
    Friend WithEvents TreeView1 As TreeView
    Friend WithEvents TextBox1 As TextBox
    

    Then I added this TextChanged event handler:

    Private Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged
        Dim nodes As TreeNode() = TreeView1.Nodes.Find(TextBox1.Text.TrimEnd("\"c), True)
        If nodes.Length > 0 Then
            Dim selectedNode As TreeNode = nodes(0)
            TreeView1.SelectedNode = selectedNode
            selectedNode.Expand()
            selectedNode.EnsureVisible()
        Else
            ' Deselect the node if no match.
            TreeView1.SelectedNode = Nothing
        End If
    End Sub
    

    Now, when I type a path, the selected node is continuously updated. Note that the Name of a node is the whole path up to this point, while the display Text is only a portion of the path.

    .TrimEnd("\"c) trims the last backslash from the text, so that we get a match while we are typing. E.g., we have a Name property "C:\Data", so when we type "C:\Data\" we still get a match.

    The second parameter Truein theFind` call says that we want to find sub-nodes as well.

    It helps to set TreeView1.HideSelection = False to display the Node selection even when the focus in the TextBox.