我想知道是否有任何方法对TreeView的特定节点进行排序(A)。
我要订购的节点是节点"Node1 \ z“
要像这样显示它:
谢谢
发布于 2022-08-03 09:26:20
一旦调用了TreeView.Sort
方法,就可以通过隐藏Sorted
属性的设置器实际应用排序的Sorted
。使用默认排序器(升序字母排序)对所有节点进行排序的控件。任何之后以不同方式对节点进行排序的尝试都会失败。您将注意到,当删除、排序和重新插入特定节点的子节点时,不会发生任何事情,因为一旦插入这些子节点,默认的排序器将干扰并恢复不同的排序。同样,所有提到的都是在任何其他排序例程之前调用.Sort
方法时。
若要重写此行为,需要为TreeView.TreeViewNodeSorter
属性提供自定义节点排序器。一个允许您按升序或降序排序节点的树或子节点的示例。
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;
}
注意这里的return 1;
,以防SortOrder.None
必须恢复,对特定节点的子节点进行排序。
TreeView
和TreeNode
类型的几个扩展方法。
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();
}
}
您可以按以下方式调用它们:
// To sort the whole thing...
YourTreeView.Sort(SortOrder.Descending);
// Or the children of the selected node for example...
YourTreeView.SelectedNode.Sort(SortOrder.Ascending);
发布于 2022-08-03 02:57:42
您的问题是如何将alpha排序(A)应用于TreeView
.中特定的单个节点。
有很多方法可以做到这一点,这些评论提到了一些好的方法。下面是一种解决方案,它使用树层次结构中的完全限定路径有效地定位目标节点。如果找到,则对其子级应用个性化排序方法(在运行时指定)。但是,首先,它必须确保TreeView
通过将其Sorted
属性设置为false
来允许这种重新排序。这种方法的一个优点是避免为整个TreeView
调用TreeView
方法,因为这会增加不必要的复杂性层。
找到目标节点
给定TreeView
的一条规则,即到任何节点(例如,@"Node1\z"
)的完全限定路径是唯一的,则可以通过为返回指定节点的TreeView
(如果没有找到null
)创建一个扩展来非常有效地获得目标。
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;
}
排序目标节点的子节点
TreeNode
的这个扩展根据作为参数传入的比较器Func
对它的子类进行排序。
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);
}
}
完全方法对TreeView.的特定节点进行排序(A)
因此,要回答的问题,有什么方法可以从any 中对TreeView的特定节点进行排序,假设我们通过为TreeView
做一个扩展来制造这样的方法。对于path
参数,指定整个层次结构路径,如@"Node1"
或@"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;
}
https://stackoverflow.com/questions/73210073
复制相似问题