【问题标题】:How can I get all expanded nodes in treeview?如何在树视图中获取所有展开的节点?
【发布时间】:2013-01-13 20:08:15
【问题描述】:

我有一个包含 TreeView 的程序。除了根和根下的两个节点之外,我的所有节点都是从数据库加载的。

当用户将数据添加到数据库时,它必须自动添加到 TreeView。我可以通过清除所有节点、添加默认节点并将包括新节点在内的所有数据添加到我的 TreeView 来成功地做到这一点,但是新 TreeView 的所有节点都被折叠了。

我们的客户希望保留所有扩展的节点,但仍要添加他刚刚添加的新数据。有没有办法知道所有展开的节点并在折叠或刷新后再次展开?感谢您的回复。

【问题讨论】:

  • Pa-post po ng 代码。示例代码。 :p
  • 为什么需要清除并重新添加而不是添加/更改单个节点?如果您有数千个节点,您的程序将...
  • 在清除树视图节点集合然后返回它的外观之前,您需要知道的究竟是什么......

标签: c# treeview nodes


【解决方案1】:

要简单地扩展节点,您可以尝试以下代码

 private void button1_Click(object sender, EventArgs e)
{
  treeView1.Nodes.Add(new TreeNode("New Node",
    new TreeNode[2] { new TreeNode("Node1"), new TreeNode("Node2") }));
  treeView1.Nodes[1].Expand();
}

希望有帮助

【讨论】:

    【解决方案2】:

    要扩展所有节点,请使用以下代码

    treeView1.ExpandAll();
    

    要扩展选定的节点,请使用以下代码

    treeView1.SelectedNode.ExpandAll();
    

    要扩展特定节点,请使用以下代码

    treeView1.Nodes[Index].Expand();
    

    【讨论】:

    • OP 询问如何获取扩展节点,而不是如何扩展节点
    • 您的回答没有回答 OP 的问题,这就是我投反对票的原因。
    【解决方案3】:

    嗨,据我了解,您希望在刷新树视图后保存树视图地图(通过添加新数据甚至删除一些数据),您希望展开所有展开的节点,而其他节点默认折叠。 解决办法是:

    1) 刷新前保存展开的树视图节点

    2) 刷新树视图数据(请注意,如果您要删除一个节点,也要将其从已保存的列表中删除)

    3) 设置之前保存的树状图

    保存树视图图(仅扩展节点)-> 此代码查看树视图节点集合并将展开的节点名称保存在字符串列表中

    List<string> collectExpandedNodes(TreeNodeCollection Nodes)
            {
                List<string> _lst = new List<string>();
                foreach (TreeNode checknode in Nodes)
                {
                    if (checknode.IsExpanded)
                        _lst.Add(checknode.Name);
                    if (checknode.Nodes.Count > 0)
                        _lst.AddRange(collectExpandedNodes(checknode.Nodes));
                }
                return _lst;
            }
    

    现在您已经在列表中收集了展开的节点名称,并且想要恢复树视图的外观,您需要 2 个函数,一个通过名称检索节点的函数和一个展开选定节点及其父节点的函数,以下代码可以:

    如果节点存在于树节点集合中,则此函数检索指向选定节点名称的指针

    TreeNode FindNodeByName(TreeNodeCollection NodesCollection , string Name)
            {
              TreeNode returnNode = null; // Default value to return
              foreach (TreeNode checkNode in NodesCollection)
                {
                    if (checkNode.Name == Name)  //checks if this node name is correct
                        returnNode = checkNode;
                    else if (checkNode.Nodes.Count > 0 ) //node has child
                    {
                        returnNode = FindNodeByName(checkNode.Nodes , Name);
                    }
    
                  if (returnNode != null) //check if founded do not continue and break
                  {
                      return returnNode;
                  }
    
                }
                //not found
                return returnNode;
            }
    

    这个函数展开节点和它的父节点

    void expandNodePath(TreeNode node)
            {
                if (node == null)
                    return;
                if (node.Level != 0) //check if it is not root
                {
                    node.Expand();
                    expandNodePath(node.Parent);
                }
                else
                {
                    node.Expand(); // this is root 
                }
    
            }
    

    下面为你展示函数的用法

    private void button4_Click(object sender, EventArgs e)
            {
                //saving expanded nodes
                List<string> ExpandedNodes = new List<string>();
                ExpandedNodes = collectExpandedNodes(treeView1.Nodes);
                //resetting tree view nodes status to colapsed
                treeView1.CollapseAll();
    
                //Restore it back
                if (ExpandedNodes.Count > 0)
                {
                    TreeNode IamExpandedNode;
                    for (int i = 0; i < ExpandedNodes.Count;i++ )
                    {
                        IamExpandedNode = FindNodeByName(treeView1.Nodes, ExpandedNodes[i]);
                        expandNodePath(IamExpandedNode);
                    }
    
                }
    
            }
    

    【讨论】:

      【解决方案4】:

      这很简单。下面,你可以看到我的递归版本:

      //List of storage ids of expanded nodes
      List<int> expandedNodeIds = new List<int>();
      //call recursive fun for our tree
      CollectExpandedNodes(tree.Nodes);
      //recursive fun for collect expanded node ids
      private void CollectExpandedNodes(TreeListNodes nodes)
      {
         foreach (TreeListNode node in nodes)
         {
            if (node.Expanded) expandedNodeIds.Add(node.Id);
            if (node.HasChildren) CollectExpandedNodes(node.Nodes);
         }
      }
      

      【讨论】:

        【解决方案5】:

        假设节点名是唯一的。

        • 使用数据库,节点名可以是表的唯一 rowid
        • 树(列表)的状态可以简单地用格式化程序保存(例如BinaryFormatter
          • 如果用户想保存状态

        只保存展开状态

        private List<string> SaveTreeState(TreeNodeCollection nodes)
        {
          List<string> nodeStates = new List<string>();
          foreach (TreeNode node in nodes)
          {
            if (node.IsExpanded) nodeStates.Add(node.Name);
            nodeStates.AddRange(SaveTreeState(node.Nodes));
          }
          return (nodeStates);
        }
        

        让树视图来查找要恢复的节点

        private void RestoreTreeState(TreeView tree, List<string> treeState)
        {
          foreach (string NodeName in treeState)
          {
            TreeNode[] NodeList = treeView1.Nodes.Find(NodeName, true);
            if (NodeList.Length > 0) // only if node after reload is avail
              NodeList[0].Expand(); 
          }
        }
        

        使用:

        List<string> StateList = SaveTreeState(treeView1.Nodes);
        ... // reload
        RestoreTreeState(treeView1, StateList);
        

        【讨论】:

          【解决方案6】:

          我知道这篇文章很旧,但如果树很深,使用树的递归遍历可能不是一个好主意。由于我没有看到任何使用非递归方式的 anwser,这里是一种在不影响性能的情况下扩展节点的解决方案。

          public static IEnumerable<TreeNodeAdv> CollectExpandedNodes(this TreeNodeAdv root)
          {
              Stack<TreeNodeAdv> s = new Stack<TreeNodeAdv>();
              s.Push(root);
              while (s.Count > 0)
              {
                  TreeNodeAdv n = s.Pop();
          
                  if (n.IsExpanded)
                      yield return n;
          
                  foreach (var child in n.Children.ToArray().Reverse())
                  {
                      s.Push(child);
                  }
              }
          }
          

          要使用此方法,您可以执行以下操作:

          foreach (TreeNodeAdv expandedNode in yourTreeView.Root.CollectExpandedNodes())
          {
              //Do processing on the expanded node or add in list.
          }
          

          extension method 使用post-order 中的Deep-First traversalyield keyword 来生成IEnumerable collection

          【讨论】:

            猜你喜欢
            • 2020-04-22
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-09-04
            • 2014-02-11
            相关资源
            最近更新 更多