我正在尝试扩展winforms TreeView控件以允许增量过滤和搜索,类似于VS2012/VS2013中的解决方案资源管理器。
理想情况下,我希望它能够以最少的代码更改替换现有的 TreeView - 就消费者而言,唯一的区别是方法 void Filter(string)
。正因为如此,我认为这对于Nodes
来说是有意义的。属性返回 TreeNodeCollection
包含所有节点,甚至由于应用的过滤器而未显示的节点。
我编写了处理过滤的代码,它实际上工作得很好,除非我访问base.Nodes
,它返回我过滤的节点,而不是完整列表。
我遇到的问题是,我无法克隆或创建 TreeNodeCollection
的新实例,因为构造函数被标记为内部。所以我理想的代码看起来像这样:
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
方法,该方法在 List<TreeNode>
中不存在.
有人对如何处理这个问题有任何建议吗?考虑到我的两个考虑因素,性能/资源方面怎么样?
谢谢
更新1:
根据帕特的建议,我决定退后一步,避免惹恼 Nodes
共。所以现在我添加了 List<TreeNode> AllNodes
属性(property)并拥有 Nodes
只是显示 TreeView 中出现的节点(过滤后的列表),所以现在更简单了。
我现在的问题是,我怎么知道什么时候 AllNodes
添加了一个项目,这样我就可以保留 Nodes
同步中?我考虑过使用 BindingList
所以我有 ListChanged
事件,但随后我需要让我的 TreeNode 和节点的子/孙/等( AllNodes[0].Nodes
)使用继承自 TreeNode
的自定义类。并更改 Nodes
属性(property),和TreeNode.Nodes
是不可重写的。还有别的办法吗?我可以创建一个名为 NodeExs 之类的新属性,但这似乎非常不直观,我可能会看到另一个开发人员稍后出现并拔出他的头发,因为 Nodes 属性在那里但不起作用。
最佳答案
关于您提出的解决方案,#2 已被淘汰,因为 TreeNode
不能属于多个控件。虽然可以创建 TreeNodeCollection
的实例通过反射,它不会很有用,因为它设计为耦合到 TreeView
或另一个TreeNode
。您将无法在集合中添加/删除节点。
Because of this, I think it would make sense for the Nodes property to return the TreeNodeCollection with ALL nodes, even ones not showing because of an applied filter.
我不同意,TreeNodeCollection
由 Nodes
返回框架和操作系统使用属性来呈现控件。您确实不想隐藏此属性或更改其功能。
如果消费者需要访问 _allNodes
,创建一个List<TreeNode> AllNodes
属性或使用自定义集合。
关于c# - 扩展 TreeView 控件以进行增量过滤/搜索,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24923419/