I would like to know if there is any method to sort (A-Z) a specific node of a TreeView.
The node I want to order is the node "Node1 \ z"
To display it like this:
H N Y Z
Thank you
I would like to know if there is any method to sort (A-Z) a specific node of a TreeView.
The node I want to order is the node "Node1 \ z"
To display it like this:
H N Y Z
Thank you
Your question is how to apply an alpha sort (A-Z) to a specific single node in a TreeView.
There are many ways to do this and the comments mention some good ones. Here is a solution that efficiently locates the target node using its fully-qualified path in the tree hierarchy. If found, it applies an individualized sort method (specified at runtime) to its children. But first, it must ensure that the TreeView will permit such reordering by setting its Sorted property to false. An advantage of this approach is that it avoids making a call the Sort method for the entire TreeView because that would add an unnecessary layer of complexity.
Find the target node
Given a rule for the TreeView that the fully-qualified path to any node (for example, @"Node1\z") is unique, the target can be obtained very efficiently by making an extension for TreeView that returns the specified node (or null if not found).
public static TreeNode Find(this TreeView treeView, string path)
{
var parse = path.Split('\\');
var nodes = treeView.Nodes;
TreeNode node = null;
foreach (var text in parse)
{
node = nodes.Cast<TreeNode>().FirstOrDefault(node => node.Text == text);
if (node == null) break;
nodes = node.Nodes;
}
return node;
}
Sort children of target node
This extension for TreeNode sorts its children according to the comparer Func passed in as an argument.
public static void Sort(
this TreeNode node,
Func<TreeNode, TreeNode, int> sorter)
{
// Make sure the TreeView will allow reordering
if (node.TreeView != null)
{
node.TreeView.Sorted = false;
}
// Copy the nodes to a list
var list = node.Nodes.Cast<TreeNode>().ToList();
// Sort the list however the `Sorter` says to.
list.Sort((a, b) => sorter(a, b));
// Clear the 'old' order
node.Nodes.Clear();
// Install the 'new' order
foreach (var sorted in list)
{
node.Nodes.Add(sorted);
}
}
Complete method to sort (A-Z) a specific node of a TreeView.
So, to answer the question Is there any method to sort a specific node of a TreeView from A-Z let's say we manufacture such a method by making an extension for TreeView that does just that. For the path argument specify the entire hierarchal path like @"Node1" or @"Node1\z".
public static bool SortIfNodeFound(
this TreeView treeView,
string path,
Func<TreeNode, TreeNode, int> sorter)
{
var node = treeView.Find(path);
node?.Sort(sorter);
return node != null;
}
Once you call the TreeView.Sort method, you actually apply the sorted TREEVIEWSTATE through the setter of the hidden Sorted property. The control by that sorts all the nodes using the default sorter, the ascending alphabetical sort. Any attempts afterwards to sort the nodes in a different way fail. You'll note that nothing happens when you remove, sort, and reinsert child nodes of a specific node because once you insert them, the default sorter will interfere and revert your different sort. Again, all the mentioned is when you call the .Sort method before any other sorting routines.
To override this behavior, you need to provide a custom node sorter for the TreeView.TreeViewNodeSorter property. An example that allows you to sort the tree or children of node in ascending or descending orders.
public class TreeNodeComparer : IComparer
{
public TreeNodeComparer(SortOrder sortOrder = SortOrder.Ascending) : base()
{
SortOrder = sortOrder;
}
public int Compare(object x, object y)
{
var xn = x as TreeNode;
var yn = y as TreeNode;
switch (SortOrder)
{
case SortOrder.Descending:
return string.Compare(xn.Text, yn.Text) * -1;
case SortOrder.Ascending:
return string.Compare(xn.Text, yn.Text);
default:
return 1;
}
}
public SortOrder SortOrder { get; set; } = SortOrder.Ascending;
}
Note return 1; here in case SortOrder.None is necessary to not revert sorting the child nodes of a specific node.
A couple of extension methods for the TreeView and TreeNode types.
public static class TreeViewExtensions
{
public static void Sort(this TreeView self, SortOrder order = SortOrder.Ascending)
{
self.TreeViewNodeSorter = new TreeNodeComparer(order);
self.Sort();
}
public static void Sort(this TreeNode self, SortOrder order = SortOrder.Ascending)
{
List<TreeNode> tmp;
TreeView tv = self.TreeView;
if (order == SortOrder.Descending)
tmp = self.Nodes.Cast<TreeNode>().OrderByDescending(n => n.Text).ToList();
else
tmp = self.Nodes.Cast<TreeNode>().OrderBy(n => n.Text).ToList();
var sorter = tv.TreeViewNodeSorter as TreeNodeComparer ?? new TreeNodeComparer();
sorter.SortOrder = SortOrder.None;
tv.TreeViewNodeSorter = sorter;
tv.BeginUpdate();
self.Nodes.Clear();
self.Nodes.AddRange(tmp.ToArray());
tv.EndUpdate();
}
}
You can call them as follows:
// To sort the whole thing...
YourTreeView.Sort(SortOrder.Descending);
// Or the children of the selected node for example...
YourTreeView.SelectedNode.Sort(SortOrder.Ascending);