2009-11-02 47 views
9

什么是使用WinForms.TreeView过滤Treeview节点的最佳/有效的方式?WinForms.TreeView - 过滤节点的最佳方式

例如:我输入“abc”,只有包含“abc”的节点变为可见。然后我输入“abcd”,我应该看到包含“abcd”文本的唯一节点。等等,所以每次我改变过滤标准时,树视图的内容也在变化。

任何想法?

- 最良好的祝愿, 穆拉特

回答

10

如果您正在寻找最佳的性能,克隆的树,然后从克隆的树中删除所有的项目,然后简单地克隆替换现有的树(和过滤)一个。

我还保留一个总是未过滤的支持树。

这适用于我有1000 - 2000个节点的相当大的树。

+0

我赞同这种做法,也涉及到其上的图案称为Memento模式。 – Burt 2009-11-02 16:16:54

+3

这不太好,在TreeNode上有一个'Visible'属性会更好。 – leppie 2009-11-02 16:18:44

+0

我会测试这个方法。感谢您的建议。我打算在TreeView上实现这个功能,最多有10-20k个节点... – 2009-11-02 16:25:53

0

如果你从叶子到父母循环,你可以找到那些在他的叶子中没有包含字符串匹配的根节点。

0

我继承的TreeView对其进行过滤(仅适用于第一级,我的工作就可以了):

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 
}