【问题标题】:Expand selected node after refresh TreeView in C#在 C# 中刷新 TreeView 后展开选定节点
【发布时间】:2011-11-29 09:13:35
【问题描述】:

我有一个包含许多项目的树形视图

当我展开一个项目及其子项并调用 refresh 方法后,展开的项子项将折叠。

你能告诉我如何存储选定的节点并在刷新后再次调用 Expand 方法...

我试过了:

 TreeNode selectedNode = new TreeNode();
 TreeNode selectedNode = SelectedTreeNode();  //method which takes selected node from TV
 RestoreFolderTreeWithLastSelectedItem(); //method which initialise treeview object
 //here I want to call Expand() method but it not exists to TreeNode.

对于树视图,我使用了Windows.Controls.treeView 命名空间 我是初学者... 谢谢

我会通过图片解释你

我展开了所有项目:

如果我按 F5 或调用 Refresh 函数 (RestoreFolderTreeWithLastSelectedItem();) 那么它们将像以下那样折叠:

而不是第一张图片...

【问题讨论】:

  • 您也可以通过将treeNode.Expanded 属性设置为true 来强制展开
  • 我在 WPF 中使用了 TreeView...它是 windows.controls.treeview
  • 如何填充树视图?如果它绑定到一个集合,我过去通过向节点绑定的类添加 IsExpanded 值并使用样式设置/取消设置此值来解决此问题。
  • 我在RestoreFolderTreeWithLastSelectedItem(); 方法之前尝试了selectedNode.isExpanded=true,但它仍然无法正常工作

标签: c# treeview


【解决方案1】:

我将它与 WinForms TreeView 一起使用。它在刷新之间保存节点展开状态:

// Save the path of the expanded tree branches
var savedExpansionState = treeView1.Nodes.GetExpansionState();

treeView1.BeginUpdate();

// TreeView is populated
// ...

// Once it is populated, we need to restore expanded nodes
treeView1.Nodes.SetExpansionState(savedExpansionState);

treeView1.EndUpdate();

以下是实现此目的的代码:

public static class TreeViewExtensions
{
    public static List<string> GetExpansionState(this TreeNodeCollection nodes)
    {
        return nodes.Descendants()
                    .Where(n => n.IsExpanded)
                    .Select(n => n.FullPath)
                    .ToList();
    }

    public static void SetExpansionState(this TreeNodeCollection nodes, List<string> savedExpansionState)
    {
        foreach (var node in nodes.Descendants()
                                  .Where(n => savedExpansionState.Contains(n.FullPath)))
        {
            node.Expand();
        }
    }

    public static IEnumerable<TreeNode> Descendants(this TreeNodeCollection c)
    {
        foreach (var node in c.OfType<TreeNode>())
        {
            yield return node;

            foreach (var child in node.Nodes.Descendants())
            {
                yield return child;
            }
        }
    }
}

【讨论】:

  • 这很有帮助。唯一的问题是,如果您有多个具有相同基本路径的节点(例如在 XML 文档中),这将打开每个相同路径,所以我将 n =&gt; n.FullPath 更改为 n =&gt; n.Tag.ToString() 并给每个节点一个不同的身份证。
  • 这为我节省了很多时间。谢谢!对于 asp.net Web 表单 TreeView 效果很好。
【解决方案2】:

这又是一个非常古老的问题,但这可能会有所帮助。 它建立在上述示例之上,但也保留了滚动位置和选择,并编写为扩展类。

这些在恢复时尽可能好地恢复 - 也就是说,如果所选节点已被删除,则其父节点将被选择/滚动到。

// To use:
// 
//     var expState = tv.GetExpandedNodesState(TreeView);
//     TreeView.Nodes.Clear();
//     ... reload...
//     tv.RestoreTreeViewState(TreeView, expState);
public static class TreeViewExtensions
{
    public static TreeViewState GetExpandedNodesState(this TreeView tree)
    {
        var expandedNodesList = new List<string>();
        foreach (TreeNode node in tree.Nodes)
        {
            UpdateExpandedList(ref expandedNodesList, node);
        }

        return new TreeViewState(expandedNodesList, tree.TopNode, tree.SelectedNode);
    }

    public static void RestoreExpandedNodesState(this TreeView tree, TreeViewState state)
    {
        tree.BeginUpdate();

        foreach (TreeNode node in tree.Nodes)
        {
            foreach (var nodeState in state.ExpandedNodes)
            {
                ExpandNodes(node, nodeState);
            }
        }

        tree.TopNode = findNodeFromPath(tree, state.TopNodePath);
        tree.SelectedNode = findNodeFromPath(tree, state.SelectedNodePath);
        tree.Focus();

        tree.EndUpdate();
    }

    static TreeNode findNodeFromPath(TreeView tree, string path)
    {
        if (string.IsNullOrWhiteSpace(path))
            return null;

        List<string> elements = path.Split(tree.PathSeparator.ToCharArray()).ToList();

        TreeNode curNode = tree.Nodes.findByText(elements[0]);
        if (curNode == null)
            return null;

        foreach (string element in elements.Skip(1))
        {
            if (curNode.Nodes.findByText(element) != null)
                curNode = curNode.Nodes.findByText(element);
            else
                break;
        }

        return curNode;
    }

    static TreeNode findByText(this TreeNodeCollection tnc, string text)
    {
        foreach (TreeNode node in tnc)
            if (node.Text == text)
                return node;
        return null;
    }

    static void UpdateExpandedList(ref List<string> expNodeList, TreeNode node)
    {
        if (node.IsExpanded) expNodeList.Add(node.FullPath);
        foreach (TreeNode n in node.Nodes)
        {
            if (n.IsExpanded)
                UpdateExpandedList(ref expNodeList, n);
        }
    }

    static void ExpandNodes(TreeNode node, string nodeFullPath)
    {
        if (node.FullPath == nodeFullPath) node.Expand();
        foreach (TreeNode n in node.Nodes)
        {
            if (n.Nodes.Count > 0)
                ExpandNodes(n, nodeFullPath);
        }
    }
}

public class TreeViewState
{
    public TreeViewState(List<string> expandedNodes, TreeNode topNode, TreeNode selectedNode)
    {
        this.ExpandedNodes = expandedNodes;
        this.TopNodePath = topNode != null ? topNode.FullPath : null;
        this.SelectedNodePath = selectedNode != null ? selectedNode.FullPath : null;
    }

    public readonly List<string> ExpandedNodes = null;
    public readonly string TopNodePath = "";
    public readonly string SelectedNodePath = "";
}

【讨论】:

    【解决方案3】:

    这很简单。

    首先,在刷新之前,我们必须存储展开节点的id:

    //CollectExpandedNodes(tree.Nodes); - call of function
    
    //this recursive function save ids of expanded nodes to expandedNodeIds
    //List<int> expandedNodeIds = new List<int>(); - list for storage id
    private void CollectExpandedNodes(TreeListNodes nodes)
    {
       foreach (TreeListNode node in nodes)
       {
          if (node.Expanded) expandedNodeIds.Add(node.Id);
          if (node.HasChildren) CollectExpandedNodes(node.Nodes);
       }
    }
    

    然后,在刷新树之后,您必须展开其 ID 存储在 expandNodeIds 中的节点:

    expandedNodeIds.ForEach((id) =>
    {
       TreeListNode node = tree.FindNodeByID(id);
       if (node != null) node.Expanded = true;
    });
    

    【讨论】:

    • 问题是关于 TreeView,而不是 TreeListNodes/dev express 控件
    【解决方案4】:

    这是老帖子,但我想如果有人来这里,这个代码片段会很有用......

    使用这个简单的代码可以保存 TreeView 状态:

    //you need to have 4 methods for it and call two of them...
    //code where treeview needs to save and restore
    var expState = GetAllExpandedNodesList(TreeView);
                        TreeView.Nodes.Clear();
                        //do something else...                    
    RestoreTreeViewState(TreeView, expState);
    //end of treeview save/restore section
    
    
            private static void UpdateExpandedList(ref List<string> expNodeList, TreeNode node)
            {
                if (node.IsExpanded) expNodeList.Add(node.FullPath);
                foreach (TreeNode n in node.Nodes)
                {
                    if (n.IsExpanded) UpdateExpandedList(ref expNodeList, n);
                }
            } 
    
            private static List<string> GetAllExpandedNodesList(TreeView tree)
            {
                var expandedNodesList = new List<string>();
    
                foreach (TreeNode node in tree.Nodes)
                {
                    UpdateExpandedList(ref expandedNodesList, node);
                }
                return expandedNodesList;
            }
    
    
            private static void ExpandNodes(TreeNode node, string nodeFullPath)
            {
                if (node.FullPath == nodeFullPath) node.Expand();
                foreach (TreeNode n  in node.Nodes)
                {
                    if (n.Nodes.Count >0) ExpandNodes(n, nodeFullPath); 
                }
            }
    
            private static void RestoreTreeViewState(TreeView tree, List<string> expandedState)
            {
                foreach (TreeNode node in tree.Nodes)
                {
                    foreach (var state in expandedState)
                    {
                        ExpandNodes(node, state);
                    }
                }
            }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-06-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多