C# 过滤TreeView节点的最佳方法
过滤C# 过滤TreeView节点的最佳方法,c#,winforms,user-interface,treeview,C#,Winforms,User Interface,Treeview,过滤Treeview节点的最佳/有效方法是什么 例如:我键入“abc”,只有包含“abc”的节点才可见。然后我键入了“abcd”,我应该可以看到包含“abcd”文本的唯一节点。以此类推,因此每次我更改筛选条件时,TreeView内容也会更改 有什么想法吗?如果您正在寻找最佳性能,请克隆树,然后从克隆树中删除所有项目,然后用克隆(并过滤)的树替换现有树 我还保留了一棵始终未经过滤的后备树 对于具有1000-2000个节点的相当大的树来说,这非常有效。如果从一个叶循环到另一个叶,您可以找到在其叶中不
Treeview
节点的最佳/有效方法是什么
例如:我键入“abc”,只有包含“abc”的节点才可见。然后我键入了“abcd”,我应该可以看到包含“abcd”文本的唯一节点。以此类推,因此每次我更改筛选条件时,TreeView
内容也会更改
有什么想法吗?如果您正在寻找最佳性能,请克隆树,然后从克隆树中删除所有项目,然后用克隆(并过滤)的树替换现有树 我还保留了一棵始终未经过滤的后备树
对于具有1000-2000个节点的相当大的树来说,这非常有效。如果从一个叶循环到另一个叶,您可以找到在其叶中不包含任何字符串匹配项的根节点。我继承TreeView对其进行过滤(仅针对第一级,我正在处理):
公共部分类winTree:TreeView
{
private NodesCollection allNodes=new NodesCollection();
[只读(正确)]
公共新节点集合节点{get{return allNodes;}}
私有字符串filtro=string.Empty;
公共字符串过滤器
{
获取{return filtro;}
设置{filtro=value;filtrarNodos();}
}
公共winTree()
{
初始化组件();
allNodes.nodead+=onnodead;
allNodes.NodeRemove+=OnNodeRemove;
allNodes.NodeClear+=onNodeClear;
}
私有void onnodead(对象发送方,事件参数e)
{
TreeNode n=(TreeNode)发送方;
if(passFilter(n))
{
base.Nodes.Add(n);
}
}
私有void OnNodeRemove(对象发送方,事件参数e)
{
删除((TreeNode)发送方);
}
私有void onNodeClear(对象发送方,事件参数e)
{
base.Nodes.Clear();
}
私有void filternodos()
{
this.BeginUpdate();
base.Nodes.Clear();
foreach(此.Nodes中的树节点n)
{
if(passFilter(n))
{
base.Nodes.Add(n);
}
}
这个.EndUpdate();
}
专用布尔通滤波器(TreeNode nodo)
{
if(string.IsNullOrWhiteSpace(filtro))
{
返回true;
}
其他的
{
返回nodo.Text.ToLower().Contains(filtro.ToLower());
}
}
}
公共类节点集合:IList
{
私有列表nodos=新列表();
公共事件处理程序nodead;
公共事件处理程序NodeRemove;
公共事件处理程序NodeClear;
nodead上的私有void(TreeNode nodo)
{
if(nodead!=null)
{
nodead(nodo,EventArgs.Empty);
}
}
私有void OnNodeRemove(TreeNode nodo)
{
if(NodeRemove!=null)
{
NodeRemove(nodo,EventArgs.Empty);
}
}
私有void OnNodesClear()
{
if(NodeRemove!=null)
{
NodesClear(this,EventArgs.Empty);
}
}
#区域IList
公共内部索引(TreeNode项)
{
返回nodos.IndexOf(项目);
OnNodeAdd(项目);
}
公共作废插入(整数索引,树节点项)
{
节点插入(索引,项目);
OnNodeAdd(项目);
}
公共无效删除(整数索引)
{
TreeNode nodo=nodos[索引];
移除节点(索引);
OnNodeRemove(nodo);
}
公共树节点此[int索引]
{
得到
{
返回nodos[index];
}
设置
{
OnNodeRemove(nodos[index]);
nodos[索引]=值;
onnodead(nodos[index]);
}
}
公共作废添加(TreeNode项)
{
添加(项);
OnNodeAdd(项目);
}
公共空间清除()
{
nodos.Clear();
OnNodesClear();
}
公共布尔包含(TreeNode项)
{
返回nodos.Contains(项目);
}
public void CopyTo(TreeNode[]数组,int-arrayIndex)
{
CopyTo(数组,数组索引);
}
公共整数计数
{
获取{return nodos.Count();}
}
公共图书馆是只读的
{
获取{return true;}
}
公共布尔删除(TreeNode项)
{
bool res=节点移除(项目);
如果(res)
{
OnNodeRemove(项目);
}
返回res;
}
公共IEnumerator GetEnumerator()
{
返回nodos.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
返回nodos.GetEnumerator();
}
#端区
}
我想提供一个更好的解决方案,问题是我不想从一个新类派生,也不想涉及更少的代码
我的解决方案:
- 按照通常不进行筛选的方式构建树
- 获取树的备份(代码如下)(我仅在进行搜索时才获取,而不仅仅是以防万一)
- 移除节点和所有东西时不要弄乱树
- 如果需要像最初一样重置树,请调用_backup.Restore()
使用System.Linq; 使用System.Windows.Forms; 公共类TreeView备份:列表 { 公共树节点父节点{get;} 公共树集合子项{get;} 公共TreeView备份(TreeNodeCollection子级,TreeNode父级=null) { 父母=父母; 儿童=儿童; AddRange(Children.Cast().Select(child=>newtreeviewbackup(child.Nodes,child)); } 公共无效恢复() { 儿童。清除(); this.ForEach(clone=>clone.Restore()); AddRange(this.Select(n=>n.Parent).ToArray(
public partial class winTree : TreeView { private NodesCollection allNodes = new NodesCollection(); [ReadOnly(true)] public new NodesCollection Nodes { get { return allNodes; } } private string filtro = string.Empty; public String Filtro { get { return filtro; } set { filtro = value; filtrarNodos(); } } public winTree() { InitializeComponent(); allNodes.NodeAdd += OnNodeAdd; allNodes.NodeRemove += OnNodeRemove; allNodes.NodesClear += OnNodesClear; } private void OnNodeAdd(object sender, EventArgs e) { TreeNode n = (TreeNode)sender; if (passFilter(n)) { base.Nodes.Add(n); } } private void OnNodeRemove(object sender, EventArgs e) { base.Nodes.Remove((TreeNode)sender); } private void OnNodesClear(object sender, EventArgs e) { base.Nodes.Clear(); } private void filtrarNodos() { this.BeginUpdate(); base.Nodes.Clear(); foreach(TreeNode n in this.Nodes) { if (passFilter(n)) { base.Nodes.Add(n); } } this.EndUpdate(); } private bool passFilter(TreeNode nodo) { if (string.IsNullOrWhiteSpace(filtro)) { return true; } else { return nodo.Text.ToLower().Contains(filtro.ToLower()); } } } public class NodesCollection : IList<TreeNode> { private List<TreeNode> nodos = new List<TreeNode>(); public event EventHandler NodeAdd; public event EventHandler NodeRemove; public event EventHandler NodesClear; private void OnNodeAdd(TreeNode nodo) { if (NodeAdd != null) { NodeAdd(nodo, EventArgs.Empty); } } private void OnNodeRemove(TreeNode nodo) { if (NodeRemove != null) { NodeRemove(nodo, EventArgs.Empty); } } private void OnNodesClear() { if (NodeRemove != null) { NodesClear(this, EventArgs.Empty); } } #region IList<TreeNode> public int IndexOf(TreeNode item) { return nodos.IndexOf(item); OnNodeAdd(item); } public void Insert(int index, TreeNode item) { nodos.Insert(index, item); OnNodeAdd(item); } public void RemoveAt(int index) { TreeNode nodo = nodos[index]; nodos.RemoveAt(index); OnNodeRemove(nodo); } public TreeNode this[int index] { get { return nodos[index]; } set { OnNodeRemove(nodos[index]); nodos[index] = value; OnNodeAdd(nodos[index]); } } public void Add(TreeNode item) { nodos.Add(item); OnNodeAdd(item); } public void Clear() { nodos.Clear(); OnNodesClear(); } public bool Contains(TreeNode item) { return nodos.Contains(item); } public void CopyTo(TreeNode[] array, int arrayIndex) { nodos.CopyTo(array, arrayIndex); } public int Count { get { return nodos.Count(); } } public bool IsReadOnly { get { return true; } } public bool Remove(TreeNode item) { bool res = nodos.Remove(item); if (res) { OnNodeRemove(item); } return res; } public IEnumerator<TreeNode> GetEnumerator() { return nodos.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return nodos.GetEnumerator(); } #endregion }
using System.Linq; using System.Windows.Forms; public class TreeViewBackup : List<TreeViewBackup> { public TreeNode Parent { get; } public TreeNodeCollection Children { get; } public TreeViewBackup(TreeNodeCollection children, TreeNode parent = null) { Parent = parent; Children = children; AddRange(Children.Cast<TreeNode>().Select(child => new TreeViewBackup(child.Nodes, child))); } public void Restore() { Children.Clear(); this.ForEach(clone => clone.Restore()); Children.AddRange(this.Select(n => n.Parent).ToArray()); } } public class Form1 { public void Filter() { _backup = new TreeViewBackup(_treeView.Nodes); _treeView.BeginUpdate(); MessWithMe(); _treeView.EndUpdate(); } public void Undo() { _treeView.BeginUpdate(); _backup.Restore(); _treeView.EndUpdate(); } }