Разверните выбранный узел после обновления TreeView в C # - PullRequest
2 голосов
/ 29 ноября 2011

У меня есть дерево с множеством предметов

Когда я раскрываю элемент и его дочерние элементы и после того, как я вызвал метод обновления, этот расширенный дочерний элемент становится свернутым.

Можете ли вы дать мне представление о том, как сохранить выбранный узел и после обновления снова вызвать метод 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 пространство имен Я начинающий ... Спасибо

Я объясню вам через изображения

Я расширил все предметы: enter image description here

Если я нажму F5 или вызову функцию Refresh (RestoreFolderTreeWithLastSelectedItem ();), то они будут свернуты, как:

enter image description here

вместо первого изображения ...

Ответы [ 4 ]

9 голосов
/ 20 ноября 2013

Я использую это с 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;
            }
        }
    }
}
1 голос
/ 06 марта 2014

Это очень просто.

Во-первых, перед обновлением мы должны сохранить идентификаторы расширенных узлов:

//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);
   }
}

И затем, после обновления вашего дерева, вы должны развернуть узлы, идентификаторы которых хранятся в extendedNodeIds:

expandedNodeIds.ForEach((id) =>
{
   TreeListNode node = tree.FindNodeByID(id);
   if (node != null) node.Expanded = true;
});
0 голосов
/ 24 января 2019

Опять же, это очень старая проблема, но опять же это может помочь.Он основан на приведенных выше примерах, но также сохраняет положение и выделение прокрутки и записывается как класс расширения.

Они восстанавливаются, насколько это возможно, при восстановлении, то есть, если выбранный узел был удален,тогда его родитель будет выбран / прокручен до.

// 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 = "";
}
0 голосов
/ 11 сентября 2015

Это старый пост, но я думаю, что если кто-то придет сюда, этот фрагмент кода будет полезен ...

Сохранить состояние 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);
                }
            }
        }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...