2009-11-02 46 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 
}