Filter a Treeview with a Textbox in a C# winforms app

前端 未结 3 865
渐次进展
渐次进展 2021-01-04 09:41

I have a TreeView in my a C# winform. I would like to be able to add a search functionality through a search box. Basically as the user types in letters (I\'m guessing on th

相关标签:
3条回答
  • 2021-01-04 09:59
    1. Every node in TreeView has Expanded and IsVisible properties. The number of items which are visible at the same time is limited (TreeView.VisibleCount). Based on this information you can reduce the number of nodes to probe dramatically.

    2. When scanning the node and it's child nodes you can abort recursion as you find the first match inside collapsed node, thus you already know it has at least one child and will be visible anyway.

    3. Perform filtering asynchronously. (use new Task() for instance) Start the first task after minimal number of chars was typed (let's say 3). Every next typed char must cancel the running task and start the new one.

    0 讨论(0)
  • 2021-01-04 10:01

    Finally this is what I did, it suits my requirements. I first make a copy of my TreeView and store into fieldsTreeCache. I then clear the fieldsTree. I then search through the cache and add any node containing my search parameter to the fieldsTree. Note here that once you search, you no longer have the parent nodes that show. You just get all of the end nodes. I did this because if not I had 2 choices:

    • Expand all the parent nodes containing childs that match but then it was slow and one parent might have 50 children which isn't great visually.
    • Not expand the parent nodes but then you just get the categories and not the children nodes that you're searching for.

      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 讨论(0)
  • 2021-01-04 10:08

    Here's a small simple example (with code from msdn) is that a very simple way to filter out the TreeView node displays.

    winforms in a tree view you can only add or remove TreeNode.

    The search for the nodes can still be improved if the nodes are stored with their data into a dictionary (with a unique key).

    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 讨论(0)
提交回复
热议问题