问题
I have a treeview with many items
When I expand an item and its childs and after I called refresh method, that expanded item childs becomes collapsed.
Can you give me an idea how to store the selected node and after refresh, to call the Expand method again...
I tried :
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.
For treeview, I used Windows.Controls.treeView
namespace
I am beginner...
Thank you
I will explain you via images
I expanded all items:
If I press F5 or call Refresh function (RestoreFolderTreeWithLastSelectedItem();) then they will be collapsed like as:
instead of first image...
回答1:
I'm using this with a WinForms TreeView. It saves the nodes expanded state between refreshes:
// 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();
Here is the code to achieve this:
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;
}
}
}
}
回答2:
It's very simple.
First, before refreshing, we must store ids of expanded nodes:
//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);
}
}
And then, after refreshing you tree, you must expand nodes whose IDs are stored in a expandedNodeIds:
expandedNodeIds.ForEach((id) =>
{
TreeListNode node = tree.FindNodeByID(id);
if (node != null) node.Expanded = true;
});
回答3:
This is old post, but I think if someone will come here, this code fragment will be useful...
To save TreeView State possible with this simple code:
//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);
}
}
}
回答4:
Again this is a very old issue, but again this might help. It builds on the above samples, but also preserves the scroll position and selection, and written as an extension class.
These are restored as well as possible upon restore - that is, if the selected node has been removed, then its parent will be selected / scrolled to.
// 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 = "";
}
来源:https://stackoverflow.com/questions/8308258/expand-selected-node-after-refresh-treeview-in-c-sharp