2011-11-24 46 views
10

我的C#winform中有一個TreeView。我希望能夠通過搜索框添加搜索功能。 基本上,當用戶輸入字母(我猜對_TextChanged事件)時,我只顯示包含輸入字母的子節點的節點...在C#winforms應用程序中使用文本框過濾TreeView

我的TreeView包含53個父節點,總數超過15000節點,所以我需要一些高性能的東西。我建立從CSV我的TreeView,我加載到數據表中,然後進行查詢與相關子節點獲取父節點...

UPDATE

我有一個想法。 最終目標是當用戶雙擊子節點時,它將被添加到listView中。

我第一次在一個簡單的列表視圖中實現了這個搜索功能,我沒有將我的數據分成不同的類別。

我的想法是,一旦用戶開始在打字的事情,我關掉我的樹狀視圖,並顯示在列表視圖,而不是...

我會嘗試和實施,看看它給性能明智..任何關於這個想法的批評都是受歡迎的。

+0

15000 - 文本節點,如果你是一個現代的PC上運行的不是太多。你甚至可以過濾樹,關鍵是要有一個聰明的策略來避免性能問題。我會試着描述一個。帶有列表的解決方案在技術上沒問題,但不是我猜測的預期和最佳用戶體驗。 –

+0

您是否嘗試過蠻力法?一個好的foreach(ParentNode.ChildNodes中的TreeNode節點)? –

回答

8

最後這是我做的,它適合我的要求。 我首先製作我的TreeView的副本並存儲到fieldsTreeCache中。我然後清理fieldsTree。然後,我搜索緩存並將包含我的搜索參數的任何節點添加到fieldsTree。請注意,一旦搜索,您不再有顯示的父節點。你只需要獲得所有的終端節點。我這樣做是因爲如果不是我有兩個選擇:

  • 展開全部包含匹配孩子的父節點,但那麼它很慢,一個家長可能有50個孩子是不是很大視覺。
  • 不擴展父節點,但你只是得到類別,而不是你正在搜索的子節點。

    void fieldFilterTxtBx_TextChanged(object sender, EventArgs e) 
    { 
        //blocks repainting tree till all objects loaded 
        this.fieldsTree.BeginUpdate(); 
        this.fieldsTree.Nodes.Clear(); 
        if (this.fieldFilterTxtBx.Text != string.Empty) 
        { 
         foreach (TreeNode _parentNode in _fieldsTreeCache.Nodes) 
         { 
          foreach (TreeNode _childNode in _parentNode.Nodes) 
          { 
           if (_childNode.Text.StartsWith(this.fieldFilterTxtBx.Text)) 
           { 
            this.fieldsTree.Nodes.Add((TreeNode)_childNode.Clone()); 
           } 
          } 
         } 
        } 
        else 
        { 
         foreach (TreeNode _node in this._fieldsTreeCache.Nodes) 
         { 
          fieldsTree.Nodes.Add((TreeNode)_node.Clone()); 
         } 
        } 
        //enables redrawing tree after all objects have been added 
        this.fieldsTree.EndUpdate(); 
    } 
    
+0

我也採用了這種方法,對我的情況效果很好。 –

+5

_treeTablesCache是​​如何創建的? – Thunder

+0

如果我有一個具有多個節點級別的節點,情況如何? –

0
  1. 每個節點在TreeView具有ExpandedIsVisible性質。同時可見的項目數量有限(TreeView.VisibleCount)。基於這些信息,您可以減少大量探測節點的數量。

  2. 當掃描節點和它的子節點可以中止遞歸,你找到的第一個比賽中倒塌節點,所以你已經知道它至少有一個孩子,是可見的反正。

  3. 異步執行過濾。 (例如使用new Task())在輸入最少數量的字符(比如說3)後啓動第一個任務。每一個下一個輸入的字符都必須取消正在運行的任務並啓動新的任務。

2

下面是一個簡單的小例子(帶有msdn中的代碼),是一種過濾TreeView節點的非常簡單的方法。

樹形視圖中的winforms只能添加或刪除TreeNode。

如果將節點與其數據一起存儲到字典(使用唯一鍵),仍然可以改進對節點的搜索。

using System.Collections; 
using System.Windows.Forms; 

namespace FilterWinFormsTreeview 
{ 
    // The basic Customer class. 
    public class Customer : System.Object 
    { 
    private string custName = ""; 
    protected ArrayList custOrders = new ArrayList(); 

    public Customer(string customername) { 
     this.custName = customername; 
    } 

    public string CustomerName { 
     get { return this.custName; } 
     set { this.custName = value; } 
    } 

    public ArrayList CustomerOrders { 
     get { return this.custOrders; } 
    } 
    } 

    // End Customer class 

    // The basic customer Order class. 
    public class Order : System.Object 
    { 
    private string ordID = ""; 

    public Order(string orderid) { 
     this.ordID = orderid; 
    } 

    public string OrderID { 
     get { return this.ordID; } 
     set { this.ordID = value; } 
    } 
    } 

    // End Order class 

    public static class TreeViewHelper 
    { 
    // Create a new ArrayList to hold the Customer objects. 
    private static ArrayList customerArray = new ArrayList(); 

    public static void FilterTreeView(TreeView treeView1, string orderText) { 
     if (string.IsNullOrEmpty(orderText)) { 
     FillMyTreeView(treeView1); 
     } else { 
     // Display a wait cursor while the TreeNodes are being created. 
     Cursor.Current = Cursors.WaitCursor; 

     // Suppress repainting the TreeView until all the objects have been created. 
     treeView1.BeginUpdate(); 

     foreach (TreeNode customerNode in treeView1.Nodes) { 
      var customer = customerNode.Tag as Customer; 
      if (customer != null) { 
      customerNode.Nodes.Clear(); 
      // Add a child treenode for each Order object in the current Customer object. 
      foreach (Order order in customer.CustomerOrders) { 
       if (order.OrderID.Contains(orderText)) { 
       var orderNode = new TreeNode(customer.CustomerName + "." + order.OrderID); 
       customerNode.Nodes.Add(orderNode); 
       } 
      } 
      } 
     } 

     // Reset the cursor to the default for all controls. 
     Cursor.Current = Cursors.Default; 

     // Begin repainting the TreeView. 
     treeView1.EndUpdate(); 
     } 
    } 

    public static void FillMyTreeView(TreeView treeView1) { 
     // Add customers to the ArrayList of Customer objects. 
     if (customerArray.Count <= 0) { 
     for (int x = 0; x < 1000; x++) { 
      customerArray.Add(new Customer("Customer" + x.ToString())); 
     } 

     // Add orders to each Customer object in the ArrayList. 
     foreach (Customer customer1 in customerArray) { 
      for (int y = 0; y < 15; y++) { 
      customer1.CustomerOrders.Add(new Order("Order" + y.ToString())); 
      } 
     } 
     } 

     // Display a wait cursor while the TreeNodes are being created. 
     Cursor.Current = Cursors.WaitCursor; 

     // Suppress repainting the TreeView until all the objects have been created. 
     treeView1.BeginUpdate(); 

     // Clear the TreeView each time the method is called. 
     treeView1.Nodes.Clear(); 

     // Add a root TreeNode for each Customer object in the ArrayList. 
     foreach (Customer customer2 in customerArray) { 
     var customerNode = new TreeNode(customer2.CustomerName); 
     customerNode.Tag = customer2; 
     treeView1.Nodes.Add(customerNode); 

     // Add a child treenode for each Order object in the current Customer object. 
     foreach (Order order1 in customer2.CustomerOrders) { 
      var orderNode = new TreeNode(customer2.CustomerName + "." + order1.OrderID); 
      customerNode.Nodes.Add(orderNode); 
     } 
     } 

     // Reset the cursor to the default for all controls. 
     Cursor.Current = Cursors.Default; 

     // Begin repainting the TreeView. 
     treeView1.EndUpdate(); 
    } 
    } 
} 
+0

'來自msdn'的代碼,鏈接在哪裏? @ punker76 – wpcoder

相關問題