使用C#winforms应用程序中的文本框过滤树视图

时间:2011-11-24 16:52:01

标签: c# winforms filter treeview

我在C#winform中有一个TreeView。我希望能够通过搜索框添加搜索功能。 基本上当用户输入字母时(我猜_TextChanged事件),我只显示包含带有输入字母的子节点的节点...

My TreeView包含53个父节点,总共超过15000个节点,所以我需要一些高性能的东西。我从一个csv构建我的TreeView,我将其加载到DataTable中然后进行查询以获取具有关联子节点的Parent节点...

更新

我有个主意。 最终目标是当用户双击子节点时,它会被添加到listView。

我首先在一个简单的列表视图中实现了这个搜索功能,我没有将我的数据分成几类。

我的想法是,一旦用户开始输入内容,我就会关闭树视图并显示列表视图......

我会尝试并实施,看看它给出了明智的表现......欢迎任何关于这个想法的评论家。

3 个答案:

答案 0 :(得分:9)

最后这就是我做的,它符合我的要求。 我首先制作TreeView的副本并存储到fieldsTreeCache中。然后我清除了字段树。然后,我搜索缓存并将包含我的搜索参数的任何节点添加到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();
    }
    

答案 1 :(得分: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();
    }
  }
}

答案 2 :(得分:0)

  1. TreeView中的每个节点都有ExpandedIsVisible个属性。同时可见的项目数量有限(TreeView.VisibleCount)。根据这些信息,您可以减少要显着探测的节点数。

  2. 扫描节点及其子节点时,您可以在折叠节点内找到第一个匹配时中止递归,因此您已经知道它至少有一个子节点,无论如何都会显示。

  3. 异步执行过滤。 (例如,使用new Task())在输入最少数量的字符后开始第一个任务(假设为3)。每个下一个键入的char都必须取消正在运行的任务并启动新任务。