Опять же, это очень старая проблема, но опять же это может помочь.Он основан на приведенных выше примерах, но также сохраняет положение и выделение прокрутки и записывается как класс расширения.
Они восстанавливаются, насколько это возможно, при восстановлении, то есть, если выбранный узел был удален,тогда его родитель будет выбран / прокручен до.
// 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 = "";
}