28

Like this:

TreeNode[] treeNodes = treeView.Nodes.Find(searchString, true);

but I want it to search in the text field instead of the name field.

ThunderGr
  • 2,297
  • 29
  • 20
Romz
  • 1,437
  • 7
  • 36
  • 63

4 Answers4

41

I am not aware of any inbuilt method but you may use LINQ

TreeNode[] treeNodes = treeView.Nodes
                                    .Cast<TreeNode>()
                                    .Where(r => r.Text == "yourText")
                                    .ToArray();
Habib
  • 219,104
  • 29
  • 407
  • 436
  • 4
    Is this more effective(faster) than a *for* loop? Can it be done without using "Cast"? And, another thing, this does not work for children in the tree. Only for the root elements. – ThunderGr Oct 21 '13 at 12:08
  • The fact that the question asks for a Find with the "search children" set to true, but in the *text* field instead of the *name* may explain the, rather austere, downvote. – ThunderGr Oct 21 '13 at 12:20
  • Since I use the treeview to display data from a class, I prefer checking the class for this kind of information(which is flat) rather than the tree(which contains lots of branches). – ThunderGr Oct 21 '13 at 12:23
  • @ThunderGr, faster than *for* loop ? I can't say, since LINQ internally uses looping. Even if there is a difference it would be negligible. And yes it doesn't search recursively, [L.B's Answer](http://stackoverflow.com/a/12388467/961113) has a recursive solution. – Habib Oct 21 '13 at 12:30
  • 9
    This method will not search child nodes – PUG Mar 13 '15 at 17:14
  • How I Populate the treeview with the TreeNode Object ? – davdomin Jul 25 '16 at 17:25
28

To search all tree nodes (not only the direct child nodes) you can use the extension method below

var nodes = treeView1.FlattenTree()
                     .Where(n => n.Text == "sometext")
                     .ToList();

--

public static class SOExtension
{
    public static IEnumerable<TreeNode> FlattenTree(this TreeView tv)
    {
        return FlattenTree(tv.Nodes);
    }

    public static IEnumerable<TreeNode> FlattenTree(this TreeNodeCollection coll)
    {
        return coll.Cast<TreeNode>()
                    .Concat(coll.Cast<TreeNode>()
                                .SelectMany(x => FlattenTree(x.Nodes)));
    }
}
L.B
  • 114,136
  • 19
  • 178
  • 224
  • `var nodes` is a set of nodes with `.Text == "sometext"`, how can I include in this set other parents nodes, whose child already in this set, so in the end I will be able to build a tree ? – Romz Sep 13 '12 at 21:57
  • it help me to filter select node based on search text `treeview.SelectedNode = treeAccount.FlattenTree().Where(p => p.Text.StartsWith(txtSearch.Text.Trim())).FirstOrDefault();` – Hisham Oct 04 '16 at 11:57
0

If I understand you correctly (you last question was very confusing), you can write a find method yourself as follows

public static TreeNode[] Find(this TreeNode motherNode, string findNodeText)
{
    List<TreeNode> nodeList = new List<TreeNode>();
    foreach (TreeNode childNode in motherNode.Nodes)
        if (childNode.Text.Equals(findNodeText, StringComparison.CurrentCulture))
            nodeList.Add(childNode);
    return nodeList.ToArray<TreeNode>();
}

This method can be used like

TreeView myTreeView = new TreeView();
foreach (TreeNode node in myTreeView.Nodes)
{
    TreeNode[] childNodes = node.Find("Text");
    // Do something...
}

I hope this helps.

MoonKnight
  • 23,214
  • 40
  • 145
  • 277
0

The following code only shows the nodes which matches the search criteria.

Copy the following code in the search event

   private void tbxSearch_KeyUp(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == Keys.Enter)
        {
            trvMenu.BeginUpdate();
            if (tbxSearch.Text.Length > 0)
            {
                for (int i = trvMenu.Nodes.Count;  i > 0  ; i--)
                {
                    NodeFiltering(trvMenu.Nodes[i - 1], tbxSearch.Text);
                }
            }
            trvMenu.EndUpdate();
        }

Then create the serch & filter function

    private bool NodeFiltering(TreeNode Nodo,string Texto)
    {
        bool resultado = false;

        if (Nodo.Nodes.Count == 0)
        {
            if (Nodo.Text.ToUpper().Contains(Texto.ToUpper()))
            {
                resultado = true;
            }
            else
            {
                Nodo.Remove();
            }
        }
        else
        {
            for (int i = Nodo.Nodes.Count; i > 0; i--)
            {
                if (NodeFiltering(Nodo.Nodes[i - 1], Texto))
                    resultado = true;
            }

            if (!resultado)
                Nodo.Remove();
        }

        return resultado;
    }

This code is pretty nice for creating Treeview menus with many levels.