TreeView Find not working
-
Hi. For the life of me, I cannot get a TreeView Find to work. I have a list of drives, folders and subfolders in my TreeView. I have googled like crazy and either find repeated references to a very simple method, or convoluted methods that seem to apply to something else. Here is a very basic procedure that fails:
Private Sub TreeView1_AfterSelect(ByVal sender As System.Object, ByVal e As System.Windows.Forms.TreeViewEventArgs) Handles TreeView1.AfterSelect
Me.TreeView1.SelectedNode = Me.TreeView1.Nodes.Find("Client Supplied Files", True)(0)
End Sub
I put the Find method in the _AfterSelect event only because I was using that event as a test area to do the find. In other words...If I clicked on any node in the tree, the event would cause the selected node to change to the one specified in the search. But alas, no go. :(( I have to be missing something really simple here. Thank you for any hints!
-
Hi. For the life of me, I cannot get a TreeView Find to work. I have a list of drives, folders and subfolders in my TreeView. I have googled like crazy and either find repeated references to a very simple method, or convoluted methods that seem to apply to something else. Here is a very basic procedure that fails:
Private Sub TreeView1_AfterSelect(ByVal sender As System.Object, ByVal e As System.Windows.Forms.TreeViewEventArgs) Handles TreeView1.AfterSelect
Me.TreeView1.SelectedNode = Me.TreeView1.Nodes.Find("Client Supplied Files", True)(0)
End Sub
I put the Find method in the _AfterSelect event only because I was using that event as a test area to do the find. In other words...If I clicked on any node in the tree, the event would cause the selected node to change to the one specified in the search. But alas, no go. :(( I have to be missing something really simple here. Thank you for any hints!
treddie wrote:
I have a list of drives, folders and subfolders in my TreeView.
How did you load them? Something similar to this[^]? In that case not all nodes will be loaded when the control shows, only the nodes that are expanded.
Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^]
-
treddie wrote:
I have a list of drives, folders and subfolders in my TreeView.
How did you load them? Something similar to this[^]? In that case not all nodes will be loaded when the control shows, only the nodes that are expanded.
Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^]
Hm...I like that solution MUCH better. But in the interests of trying to understand why "my" version won't work (it was an online TreeView demo that I modified slightly), no, it was a fully recursive method. Please see code below:
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Go_cmd.Click
'Get a list of drives:
Dim drives As System.Collections.ObjectModel.ReadOnlyCollection(Of IO.DriveInfo) = My.Computer.FileSystem.Drives
Dim rootDir As String = String.Empty'Now loop thru each drive and populate the treeview: For i As Integer = 0 To drives.Count - 1 System.Windows.Forms.Application.DoEvents() rootDir = drives(i).Name 'Add this drive as a root node: TreeView1.Nodes.Add(rootDir) 'Populate this root node: PopulateTreeView(rootDir, TreeView1.Nodes(i))
NextDrive:
Next iEnd Sub
Private Sub PopulateTreeView(ByVal dir As String, ByVal parentNode As TreeNode)
Dim folder As String = String.EmptyTry Dim folders() As String = IO.Directory.GetDirectories(dir) If folders.Length <> 0 Then Dim childNode As TreeNode = Nothing For Each folder In folders System.Windows.Forms.Application.DoEvents() childNode = New TreeNode(folder) parentNode.Nodes.Add(childNode) PopulateTreeView(folder, childNode) Next folder End If Catch ex As System.IO.IOException parentNode.Nodes.Add(folder & ": Drive not Ready") Catch ex As UnauthorizedAccessException parentNode.Nodes.Add(folder & ": Access Denied") End Try
End Sub
Private Sub TreeView1_AfterSelect(ByVal sender As System.Object, ByVal e As System.Windows.Forms.TreeViewEventArgs) Handles TreeView1.AfterSelect
If Text <> String.Empty Then Dim arr As TreeNode() = TreeView1.Nodes.Find("Client Supplied Files", True) For i = 0 To arr.Length - 1 TreeView1.SelectedNode = arr(i) Next End If
End Sub
End Class
-
Hm...I like that solution MUCH better. But in the interests of trying to understand why "my" version won't work (it was an online TreeView demo that I modified slightly), no, it was a fully recursive method. Please see code below:
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Go_cmd.Click
'Get a list of drives:
Dim drives As System.Collections.ObjectModel.ReadOnlyCollection(Of IO.DriveInfo) = My.Computer.FileSystem.Drives
Dim rootDir As String = String.Empty'Now loop thru each drive and populate the treeview: For i As Integer = 0 To drives.Count - 1 System.Windows.Forms.Application.DoEvents() rootDir = drives(i).Name 'Add this drive as a root node: TreeView1.Nodes.Add(rootDir) 'Populate this root node: PopulateTreeView(rootDir, TreeView1.Nodes(i))
NextDrive:
Next iEnd Sub
Private Sub PopulateTreeView(ByVal dir As String, ByVal parentNode As TreeNode)
Dim folder As String = String.EmptyTry Dim folders() As String = IO.Directory.GetDirectories(dir) If folders.Length <> 0 Then Dim childNode As TreeNode = Nothing For Each folder In folders System.Windows.Forms.Application.DoEvents() childNode = New TreeNode(folder) parentNode.Nodes.Add(childNode) PopulateTreeView(folder, childNode) Next folder End If Catch ex As System.IO.IOException parentNode.Nodes.Add(folder & ": Drive not Ready") Catch ex As UnauthorizedAccessException parentNode.Nodes.Add(folder & ": Access Denied") End Try
End Sub
Private Sub TreeView1_AfterSelect(ByVal sender As System.Object, ByVal e As System.Windows.Forms.TreeViewEventArgs) Handles TreeView1.AfterSelect
If Text <> String.Empty Then Dim arr As TreeNode() = TreeView1.Nodes.Find("Client Supplied Files", True) For i = 0 To arr.Length - 1 TreeView1.SelectedNode = arr(i) Next End If
End Sub
End Class
-
Unless some other members beats me to it, I'll write a search-implementation tomorrow. Now, :zzz:
-
Here is a code that I made by several examples that I found:
Public Class cTreeviewFind
Inherits TreeView
#Region "Functions"
Function SearchTree(ByVal root As TreeNode, ByVal text As String) As System.Collections.Generic.List(Of TreeNode)
Dim nodes As New System.Collections.Generic.List(Of TreeNode)()' case insensitive If root.Text.ToUpper().Contains(text.ToUpper()) Then nodes.Add(root) End If For Each node As TreeNode In root.Nodes Dim subNodes As System.Collections.Generic.List(Of TreeNode) = SearchTree(node, text) If (subNodes.Count > 0) Then nodes.AddRange(subNodes) End If Next Return nodes End Function ''' ''' Zoek in welke node een tekst voorkomt ''' ''' ''' ''' ''' ''' ''' Public Function FindNode(ByVal \_nodeCollection As TreeNode, ByVal SearchVal As String, Optional ByVal CaseSensitief As Boolean = False, Optional ByVal CompleteValue As Boolean = False, Optional ByVal refind As Boolean = False) As TreeNode Dim tmpNode As TreeNode = Nothing Static bFoundSelectedNode As Boolean If refind Then bFoundSelectedNode = False If Me.SelectedNode.Equals(Me.Nodes(0)) Then bFoundSelectedNode = True End If For Each \_c As TreeNode In \_nodeCollection.Nodes If \_c.Equals(Me.SelectedNode) Then bFoundSelectedNode = True End If If bFoundSelectedNode = False Then If \_c.Nodes.Count > 0 Then tmpNode = FindNode(\_c, SearchVal, CaseSensitief, CompleteValue) If bFoundSelectedNode = True AndAlso Not tmpNode Is Nothing Then Return tmpNode End If End If Else If CaseSensitief Then If CompleteValue Then If \_c.Text = SearchVal AndAlso \_c.Equals(Me.SelectedNode) = False Then Return \_c If \_c.Nodes.Count > 0 Then tmpNode = FindNode(\_c, SearchVal, CaseSensitief, CompleteValue) If Not tmpNode Is Nothing Then Return tmpNode End If Else If \_c.Text.IndexOf(SearchVal) >= 0 AndAlso \_c.Equals(Me.SelectedNode) = False Then Return \_c If \_c.Nodes.Count
-
Here is a code that I made by several examples that I found:
Public Class cTreeviewFind
Inherits TreeView
#Region "Functions"
Function SearchTree(ByVal root As TreeNode, ByVal text As String) As System.Collections.Generic.List(Of TreeNode)
Dim nodes As New System.Collections.Generic.List(Of TreeNode)()' case insensitive If root.Text.ToUpper().Contains(text.ToUpper()) Then nodes.Add(root) End If For Each node As TreeNode In root.Nodes Dim subNodes As System.Collections.Generic.List(Of TreeNode) = SearchTree(node, text) If (subNodes.Count > 0) Then nodes.AddRange(subNodes) End If Next Return nodes End Function ''' ''' Zoek in welke node een tekst voorkomt ''' ''' ''' ''' ''' ''' ''' Public Function FindNode(ByVal \_nodeCollection As TreeNode, ByVal SearchVal As String, Optional ByVal CaseSensitief As Boolean = False, Optional ByVal CompleteValue As Boolean = False, Optional ByVal refind As Boolean = False) As TreeNode Dim tmpNode As TreeNode = Nothing Static bFoundSelectedNode As Boolean If refind Then bFoundSelectedNode = False If Me.SelectedNode.Equals(Me.Nodes(0)) Then bFoundSelectedNode = True End If For Each \_c As TreeNode In \_nodeCollection.Nodes If \_c.Equals(Me.SelectedNode) Then bFoundSelectedNode = True End If If bFoundSelectedNode = False Then If \_c.Nodes.Count > 0 Then tmpNode = FindNode(\_c, SearchVal, CaseSensitief, CompleteValue) If bFoundSelectedNode = True AndAlso Not tmpNode Is Nothing Then Return tmpNode End If End If Else If CaseSensitief Then If CompleteValue Then If \_c.Text = SearchVal AndAlso \_c.Equals(Me.SelectedNode) = False Then Return \_c If \_c.Nodes.Count > 0 Then tmpNode = FindNode(\_c, SearchVal, CaseSensitief, CompleteValue) If Not tmpNode Is Nothing Then Return tmpNode End If Else If \_c.Text.IndexOf(SearchVal) >= 0 AndAlso \_c.Equals(Me.SelectedNode) = False Then Return \_c If \_c.Nodes.Count
-
FINALLY! One that actually works! :). Now the big $30,000 question is, why doesn't the method that MS and so many others suggest NOT work? Me.TreeView1.SelectedNode = Me.TreeView1.Nodes.Find("Client Supplied Files", True)
treddie wrote:
Now the big $30,000 question is, why doesn't the method that MS and so many others suggest NOT work?
Here's a free answer to an expensive question; due to the difference between the nodes' key and it's label. The "find" method works on keys[^] (the name of the node), not on the text being displayed. If you only pass a single string when creating a node, it will not have a name. Try the example below and play a bith with it.
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
AddHandler btn.Click, Sub(s As Object, e As EventArgs)
Dim foundNodes As TreeNode() = TreeView1.Nodes.Find("Node 39", True)
If foundNodes.Length > 0 Then
TreeView1.SelectedNode = foundNodes(0)
TreeView1.Focus()
End If
End Sub
TreeView1.Dock = DockStyle.Fill
For i As Integer = 0 To 40
Dim key As String = String.Format("Node {0}", i)
Dim label As String = String.Format("Label {0}", i)
TreeView1.Nodes.Add(key, label)
Next
f.Controls.Add(TreeView1)
f.Controls.Add(btn)
f.ShowDialog()
End Using
End Sub
End ModuleBastard Programmer from Hell :suss: If you can't read my code, try converting it here[^]
-
treddie wrote:
Now the big $30,000 question is, why doesn't the method that MS and so many others suggest NOT work?
Here's a free answer to an expensive question; due to the difference between the nodes' key and it's label. The "find" method works on keys[^] (the name of the node), not on the text being displayed. If you only pass a single string when creating a node, it will not have a name. Try the example below and play a bith with it.
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
AddHandler btn.Click, Sub(s As Object, e As EventArgs)
Dim foundNodes As TreeNode() = TreeView1.Nodes.Find("Node 39", True)
If foundNodes.Length > 0 Then
TreeView1.SelectedNode = foundNodes(0)
TreeView1.Focus()
End If
End Sub
TreeView1.Dock = DockStyle.Fill
For i As Integer = 0 To 40
Dim key As String = String.Format("Node {0}", i)
Dim label As String = String.Format("Label {0}", i)
TreeView1.Nodes.Add(key, label)
Next
f.Controls.Add(TreeView1)
f.Controls.Add(btn)
f.ShowDialog()
End Using
End Sub
End ModuleBastard Programmer from Hell :suss: If you can't read my code, try converting it here[^]
Heheh...Your code threw me for a second. It looks like you did a C#-to-vb conversion. :) But I figured it out and made the mods to get it to work in vb.Net. (I'm not a "C" guy). Here is my change to your translation, with a caption added to the button:
Imports System.Windows.Forms
Module Module1
Dim TreeView1 As New TreeViewSub Main()
'This demo is a test of how a TreeView search behaves for a node name (key) vs. the TEXT of the node as
'seen in the TreeView. Searching for the text will fail. YOU NEED THE NAME (KEY) TO DO THE SEARCH.Using f As New Form Dim btn As New Button btn.Dock = DockStyle.Top btn.Text = "Find ""Label 39""" AddHandler btn.Click, AddressOf BClick TreeView1.Dock = DockStyle.Fill For i As Integer = 0 To 40 Dim key As String 'Comment-out this line, and the search will fail, 'because a node's NAME (its KEY) is NOT its TEXT LABEL!: key = String.Format("Node {0}", i) Dim label As String = String.Format("Label {0}", i) TreeView1.Nodes.Add(key, label) Next i f.Controls.Add(TreeView1) f.Controls.Add(btn) f.ShowDialog() End Using
End Sub
Private Sub BClick(ByVal s As Object, ByVal e As EventArgs)
Dim foundNodes As TreeNode() = TreeView1.Nodes.Find("Node 39", True)
If foundNodes.Length > 0 Then
TreeView1.SelectedNode = foundNodes(0)
TreeView1.Focus()
End IfEnd Sub
End Module
This makes complete sense now...The name/key is NOT the text label. Although it is best to make sure the key = text, so that you don't get confused by the results.
-
Heheh...Your code threw me for a second. It looks like you did a C#-to-vb conversion. :) But I figured it out and made the mods to get it to work in vb.Net. (I'm not a "C" guy). Here is my change to your translation, with a caption added to the button:
Imports System.Windows.Forms
Module Module1
Dim TreeView1 As New TreeViewSub Main()
'This demo is a test of how a TreeView search behaves for a node name (key) vs. the TEXT of the node as
'seen in the TreeView. Searching for the text will fail. YOU NEED THE NAME (KEY) TO DO THE SEARCH.Using f As New Form Dim btn As New Button btn.Dock = DockStyle.Top btn.Text = "Find ""Label 39""" AddHandler btn.Click, AddressOf BClick TreeView1.Dock = DockStyle.Fill For i As Integer = 0 To 40 Dim key As String 'Comment-out this line, and the search will fail, 'because a node's NAME (its KEY) is NOT its TEXT LABEL!: key = String.Format("Node {0}", i) Dim label As String = String.Format("Label {0}", i) TreeView1.Nodes.Add(key, label) Next i f.Controls.Add(TreeView1) f.Controls.Add(btn) f.ShowDialog() End Using
End Sub
Private Sub BClick(ByVal s As Object, ByVal e As EventArgs)
Dim foundNodes As TreeNode() = TreeView1.Nodes.Find("Node 39", True)
If foundNodes.Length > 0 Then
TreeView1.SelectedNode = foundNodes(0)
TreeView1.Focus()
End IfEnd Sub
End Module
This makes complete sense now...The name/key is NOT the text label. Although it is best to make sure the key = text, so that you don't get confused by the results.
-
treddie wrote:
It looks like you did a C#-to-vb conversion. :)
Thanks; no conversion, it was a new console-application in the VS-IDE :)