在树视图中搜索特定字符串

时间:2017-02-17 10:11:15

标签: c# winforms

我试图在TreeView中搜索特定字符串,一旦找到了节点的索引,我希望返回其索引并更改该特定节点的背景颜色,但是我当前的代码没有似乎返回任何匹配,除非它是根节点:

    private void ApplyRulesetColors()
    {
        foreach (var rule in dictOverwriteEntries)
        {
            int iResultIndex = SearchTreeView(rule.Key, tvDirectoryStructure.Nodes);

            if (iResultIndex > -1)
            {
                switch (rule.Value)
                {
                    case Operations.Overwrite:
                        tvDirectoryStructure.Nodes[iResultIndex].BackColor = Color.Red;
                        break;
                    case Operations.Delete:
                        break;
                    case Operations.None:
                        break;
                    default:
                        break;
                }
            }
        }
    }

这是应该搜索树视图的函数:

    private int SearchTreeView(string p_sSearchTerm, TreeNodeCollection p_Nodes)
    {
        foreach (TreeNode node in p_Nodes)
        {
            if (node.Text == p_sSearchTerm)
            {
                return node.Index;
            }

            if (node.Nodes.Count > 0)
                SearchTreeView(p_sSearchTerm, node.Nodes);
        }

        return -1;
    }

此时只会在根节点值上匹配并返回0,即使(据我所知)它应该搜索整个树,包括子节点。

谢谢。

2 个答案:

答案 0 :(得分:2)

您的代码中存在两个问题:

  1. 如果在根节点的子节点中找不到节点,则不返回递归调用的结果,而是-1
  2. 您返回节点Index,这是节点的父子集合中的索引,而不是全局索引。
  3. 我建议改为返回TreeNode本身。像这样改变你的方法:

    private TreeNode SearchTreeView(string p_sSearchTerm, TreeNodeCollection p_Nodes)
    {
        foreach (TreeNode node in p_Nodes)
        {
            if (node.Text == p_sSearchTerm)
                return node;
    
            if (node.Nodes.Count > 0)
            {
                TreeNode child = SearchTreeView(p_sSearchTerm, node.Nodes);
                if (child != null) return child;
            }
        }
    
        return null;
    }
    

    并使用它:

     private void ApplyRulesetColors()
     {
        foreach (var rule in dictOverwriteEntries)
        {
            TreeNode resultNode = SearchTreeView(rule.Key, tvDirectoryStructure.Nodes);
    
            if (resultNode != null)
            {
                switch (rule.Value)
                {
                    case Operations.Overwrite:
                        resultNode.BackColor = Color.Red;
                        break;
                    case Operations.Delete:
                        break;
                    case Operations.None:
                        break;
                    default:
                        break;
                }
            }
       }
    }
    

    但请注意,此代码只会找到第一个匹配的节点。我不知道您的树是否可能包含多个具有相同Text的节点。在这种情况下,您应该使用另一个属性来标识节点。

答案 1 :(得分:2)

您需要返回TreeNode本身而不是它的索引,因为索引是相对于定位节点的父节点。此外,您的递归SearchTreeView在递归调用期间找到它时不会返回该元素。下面的代码将起作用并返回TreeNode本身,您可以根据需要设置样式。

您可能希望知道您的方法效率不高,因为您需要按照列表中的规则多次迭代树。如果迭代树一次,然后匹配列表中每个节点的规则,则可能更有效。您的代码可能是应用访客模式的好例子:http://www.dofactory.com/net/visitor-design-pattern

无论如何,这是正确的SearchTreeView

private TreeNode SearchTreeView(string p_sSearchTerm, TreeNodeCollection p_Nodes)
{
    foreach (TreeNode node in p_Nodes)
    {
        if (node.Text == p_sSearchTerm)
        {
            return node;
        }

        if (node.Nodes.Count > 0)
        {
            var result = SearchTreeView(p_sSearchTerm, node.Nodes);
            if (result != null)
            {
                return result;
            }
        }
    }

    return null;
}