Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 71 additions & 11 deletions src/System.Windows.Forms/src/System/Windows/Forms/TreeNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ internal TreeNodeImageIndexer StateImageIndexer
}

internal int index; // our index into our parents child array
internal readonly List<TreeNode> childNodes = new();
internal List<TreeNode> childNodes = new();
internal TreeNode parent;
internal TreeView treeView;
private bool expandOnRealization;
Expand Down Expand Up @@ -1249,23 +1249,83 @@ public static TreeNode FromHandle(TreeView tree, IntPtr handle)

private void SortChildren(TreeView parentTreeView)
{
var nodeCount = childNodes.Count;
if (nodeCount > 0)
if (childNodes.Count <= 0)
{
List<TreeNode> newOrder = new(nodeCount);
if (parentTreeView?.TreeViewNodeSorter is null)
{
childNodes.Sort((x, y) => Application.CurrentCulture.CompareInfo.Compare(x.Text, y.Text, CompareOptions.None));
}
else
return;
}

List<TreeNode> newOrder = new(childNodes.Count);
if (parentTreeView is null || parentTreeView.TreeViewNodeSorter is null)
{
CompareInfo compare = Application.CurrentCulture.CompareInfo;
for (int i = 0; i < childNodes.Count; i++)
{
childNodes.Sort(parentTreeView.TreeViewNodeSorter.Compare);
newOrder.Add(childNodes[i]);

int min = -1;
for (int j = 0; j < childNodes.Count; j++)
{
if (childNodes[j] is null)
{
continue;
}

if (min == -1)
{
min = j;
continue;
}

if (compare.Compare(childNodes[j].Text, childNodes[min].Text) <= 0)
{
min = j;
}
}

Debug.Assert(min != -1, "Bad sorting");
newOrder[i] = childNodes[min];
childNodes[min] = null!;
newOrder[i].index = i;
newOrder[i].SortChildren(parentTreeView);
}

childNodes = newOrder;
}
else
{
IComparer sorter = parentTreeView.TreeViewNodeSorter;
for (int i = 0; i < childNodes.Count; i++)
{
childNodes[i].SortChildren(parentTreeView);
newOrder.Add(childNodes[i]);

int min = -1;
for (int j = 0; j < childNodes.Count; j++)
{
if (childNodes[j] is null)
{
continue;
}

if (min == -1)
{
min = j;
continue;
}

if (sorter.Compare(childNodes[j] /*previous*/, childNodes[min] /*current*/) <= 0)
{
min = j;
}
}

Debug.Assert(min != -1, "Bad sorting");
newOrder[i] = childNodes[min];
childNodes[min] = null!;
newOrder[i].index = i;
newOrder[i].SortChildren(parentTreeView);
}

childNodes = newOrder;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7114,6 +7114,52 @@ public void TreeView_TreeViewNodeSorter_ComparesTreeNodes()
treeView.TreeViewNodeSorter = treeSorter;
}

[WinFormsTheory]
[InlineData("A", "B")]
[InlineData("A", "A")]
[InlineData("B", "A")]
public void Clear_AfterSort_ShouldNotGetStuck(string firstNodeText, string secondNodeText)
{
using TreeView treeView = new();
TreeNode parent = new("Parent");
treeView.Nodes.Add(parent);

TreeNode firstNode = new(firstNodeText);
parent.Nodes.Add(firstNode);
TreeNode secondNode = new(secondNodeText);
parent.Nodes.Add(secondNode);

treeView.Sort();

Stopwatch timer = new();
timer.Start();
parent.Nodes.Clear();
timer.Stop();
Assert.True(timer.ElapsedMilliseconds <= 500);
}

[WinFormsTheory]
[InlineData("A", "B")]
[InlineData("A", "A")]
[InlineData("B", "A")]
public void Remove_AfterSort_ShouldNotThrowException(string firstNodeText, string secondNodeText)
{
using TreeView treeView = new();
TreeNode parent = new("Parent");
treeView.Nodes.Add(parent);

TreeNode firstNode = new(firstNodeText);
parent.Nodes.Add(firstNode);
TreeNode secondNode = new(secondNodeText);
parent.Nodes.Add(secondNode);

treeView.Sort();

parent.Nodes.Remove(firstNode);

parent.Nodes.Remove(secondNode);
}

private class SubTreeView : TreeView
{
public new bool CanEnableIme => base.CanEnableIme;
Expand Down