Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/328.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 扩展TreeView控件以进行增量筛选/搜索_C#_.net_Winforms_Treeview - Fatal编程技术网

C# 扩展TreeView控件以进行增量筛选/搜索

C# 扩展TreeView控件以进行增量筛选/搜索,c#,.net,winforms,treeview,C#,.net,Winforms,Treeview,我正在尝试扩展winforms TreeView控件,以允许类似于VS2012/VS2013中的解决方案资源管理器的增量筛选和搜索 理想情况下,我希望它能够用最少的代码更改来替换现有的TreeView-就消费者而言,唯一的区别是方法void Filter(string)。因此,我认为Nodes属性返回所有节点的TreeNodeCollection是有意义的,即使是由于应用了过滤器而未显示的节点 我编写了用于处理过滤的代码,它实际上运行得很好,除非当我访问base.Nodes时,它返回我的过滤节点

我正在尝试扩展winforms TreeView控件,以允许类似于VS2012/VS2013中的解决方案资源管理器的增量筛选和搜索

理想情况下,我希望它能够用最少的代码更改来替换现有的TreeView-就消费者而言,唯一的区别是方法
void Filter(string)
。因此,我认为
Nodes
属性返回所有节点的
TreeNodeCollection
是有意义的,即使是由于应用了过滤器而未显示的节点

我编写了用于处理过滤的代码,它实际上运行得很好,除非当我访问
base.Nodes
时,它返回我的过滤节点,而不是完整列表

我遇到的问题是,我无法克隆或创建
TreeNodeCollection
的新实例,因为构造函数被标记为internal。因此,我的理想代码如下所示:

public class TreeViewEx : TreeView
{
    // results in a compiler error:
    private TreeNodeCollection _allNodes = new TreeNodeCollection();

    public new TreeNodeCollection Nodes { get { return _allNodes; } }

    public TreeNodeCollection FilteredNodes { get { return base.Nodes; } }

    public void Filter(string searchString)
    {
        base.BeginUpdate();
        base.Nodes.Clear();
        foreach (TreeNode node in FilterInternal(_allNodes, searchString))
        {
            base.Nodes.Add(node);
        }
        base.EndUpdate();
    }
}
如您所见,我正在尝试将UI中显示的节点与使用者将访问的节点解耦。当然,由于
TreeNodeCollection
只有一个内部构造函数,我无法创建新实例或克隆它

我考虑过这两种选择,但都不是好的解决方案:

  • 使用反射为第二个列表实例化
    TreeNodeCollection
    对象(由于内部构造函数)。这个选项似乎比#2更有效,但当然我正在创建一个不应该创建的对象的实例
  • 在内存中实例化第二个TreeView,并使用其中的Nodes属性来维护第二个列表。这似乎是一个很大的开销
  • 我希望最终结果仍然是
    TreeNodeCollection
    ,因此可以使用TreeView用最少的代码替换现有控件,并且我们确实有几个地方使用
    Find
    方法,这在
    列表中不存在

    有人对如何处理这个问题有什么建议吗?在性能/资源方面,我的两个考虑因素是什么

    多谢各位

    更新1:

    根据Pat的建议,我决定后退一步,避免完全弄乱
    节点。现在我添加了一个
    列出所有节点
    属性,让
    节点
    只显示树状视图(过滤列表)中出现的节点,所以现在更简单了


    我现在的问题是,如何知道
    AllNodes
    何时添加了一个项目,以便保持
    Nodes
    同步?我考虑过使用
    绑定列表
    ,因此我有了
    列表更改
    事件,但是我需要让我的TreeNode和节点的子节点/grand children/etc(
    所有节点[0]。节点
    )使用从
    TreeNode
    继承的自定义类,并更改
    节点
    属性,和
    TreeNode.Nodes
    不可重写。还有别的办法吗?我可以创建一个名为NodeExs或其他什么的新属性,但这似乎非常不直观,我可以看到另一个开发人员随后出现,并拔出他的头发,因为Nodes属性在那里但不起作用。

    关于您提出的解决方案,#2不起作用,因为
    TreeNode
    不能属于多个控件。虽然可以通过反射创建
    TreeNodeCollection
    的实例,但它不会非常有用,因为它被设计为与
    TreeView
    或另一个
    TreeNode
    耦合。您将无法从集合中添加/删除节点

    因此,我认为使用Nodes属性是有意义的 返回包含所有节点的TreeNodeCollection,即使是未显示的节点 因为应用了过滤器

    我不同意,由
    节点
    属性返回的
    TreeNodeCollection
    被框架和操作系统用来呈现控件。您确实不想隐藏此属性或更改其功能


    如果消费者需要访问
    \u allNodes
    ,请创建
    列表allNodes
    属性或使用自定义集合

    我发现
    TreeNodeCollection
    只能用于读取列出的节点。相反,我使用了
    List
    来列出节点。在我的项目中,我在
    树视图
    上为每个级别创建了一个
    列表
    。我在启动时填写
    TreeView
    的同时填写了列表。最后,我使用
    AddRange()
    创建并合并了一个所有节点的列表。通过这种方式,我列出了所有节点并进行了分类

    创建此类列表既简单又快速。我还创建了一个所有节点列表的
    列表
    版本,我为我的
    文本框
    设置了一个
    AutoCompleteCustomSource
    。这样我就可以使用
    TextBox
    AutoComplete
    来搜索节点

    我会为消费者和其他类别列出不同的清单。然后,我只将满足给定条件的项添加到
    树视图中。您还可以使用
    treeView.Nodes.Remove()
    删除任何节点。您仍然可以将实际节点存储在列表中,并且可以稍后再将其添加回来


    这些只是一些想法。

    您可以克隆树并删除不需要的树,然后将其分配回树视图。@terrybozzio感谢您的回复。问题是,由于内部构造函数的原因,
    TreeNodeCollection
    无法克隆。我可以把它放在
    列表中,但这还有一些其他障碍需要克服……不相关:Visual Studio放弃了古老的winforms并用WPF重写是有原因的。您可以在WPF中使用两行代码来实现这一点,而无需诉诸任何可怕的黑客攻击,也无需对标准TreeView.Pat进行子类化,谢谢您的回复。我相信使用t