什麼是使用WinForms.TreeView過濾Treeview節點的最佳/有效的方式?WinForms.TreeView - 過濾節點的最佳方式
例如:我輸入「abc」,只有包含「abc」的節點變爲可見。然後我輸入「abcd」,我應該看到包含「abcd」文本的唯一節點。等等,所以每次我改變過濾標準時,樹視圖的內容也在變化。
任何想法?
- 最良好的祝願, 穆拉特
什麼是使用WinForms.TreeView過濾Treeview節點的最佳/有效的方式?WinForms.TreeView - 過濾節點的最佳方式
例如:我輸入「abc」,只有包含「abc」的節點變爲可見。然後我輸入「abcd」,我應該看到包含「abcd」文本的唯一節點。等等,所以每次我改變過濾標準時,樹視圖的內容也在變化。
任何想法?
- 最良好的祝願, 穆拉特
如果您正在尋找最佳的性能,克隆的樹,然後從克隆的樹中刪除所有的項目,然後簡單地克隆替換現有的樹(和過濾)一個。
我還保留一個總是未過濾的支持樹。
這適用於我有1000 - 2000個節點的相當大的樹。
如果你從葉子到父母循環,你可以找到那些在他的葉子中沒有包含字符串匹配的根節點。
我繼承的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
}
我贊同這種做法,也涉及到其上的圖案稱爲Memento模式。 – Burt 2009-11-02 16:16:54
這不太好,在TreeNode上有一個'Visible'屬性會更好。 – leppie 2009-11-02 16:18:44
我會測試這個方法。感謝您的建議。我打算在TreeView上實現這個功能,最多有10-20k個節點... – 2009-11-02 16:25:53