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