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();
          }
      }