Demo: reproduce TreeView AddRange sort-order reversal (and verify AppContext switch)#27
Conversation
…r reversal Adds a minimal, self-contained repro to the WinForms demo app (WinformsControlsTest) showing that TreeNodeCollection.AddRange reverses the order of equal-comparing nodes when TreeView.Sorted is true. This is a framework-level behavior change vs .NET 8 / .NET Framework, independent of any application logic. The demo can also run headlessly and flip the System.Windows.Forms.TreeNodeCollectionAddRangeRespectsSortOrder AppContext switch (PR dotnet#11423), so the switch's effect can be verified empirically. Demo only - no product code is changed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
| return true; | ||
| } | ||
|
|
||
| // A sorter that treats every node as equal, like several identically described items. |
There was a problem hiding this comment.
The three key elements that trigger defects ----- 1:
Corresponding to CargoWise's PkgPackageComparer, it returns 0 for an empty Pallet.
https://github.com/WiseTechGlobal/CargoWise/blob/71b809691cfb365b052e73648708f4ee6abf85d0/Enterprise/Product/Operations/Packing/Packing.Business/PkgPackage/PkgPackageComparer.cs
This is why the problem only arises when we add Pallets with same name.
| return $"[{arguments}] error: {ex.Message}"; | ||
| } | ||
| } | ||
|
|
There was a problem hiding this comment.
Create nodes with sequential numbers.
| AppContext.SetSwitch(SwitchName, switchValue); | ||
| } | ||
|
|
||
| TreeNode[] nodes = CreatePalletNodes(PalletCount); |
There was a problem hiding this comment.
The three key elements that trigger defects ----- 2:
Correspond to 'Sorted=true' in PackingTreeView
https://github.com/WiseTechGlobal/CargoWise/blob/71b809691cfb365b052e73648708f4ee6abf85d0/Enterprise/Product/Operations/Packing/Packing.GUI/PackingForm/TreeView/PackingTreeView.cs#L144
|
|
||
| TreeNode[] nodes = CreatePalletNodes(PalletCount); | ||
| using TreeView treeView = new() { Sorted = true, TreeViewNodeSorter = new AlwaysEqualComparer() }; | ||
| treeView.CreateControl(); |
There was a problem hiding this comment.
The three key elements that trigger defects ----- 3:
AddRange would add nodes with increasing sequence, and trigger net10 reverse traversal
for (int i = nodes.Length - 1; i >= 0; i--) { AddInternal(nodes[i], delta: i); }
| string switchArg = args.FirstOrDefault(a => a.StartsWith("--switch:", StringComparison.OrdinalIgnoreCase)); | ||
| if (switchArg is not null && bool.TryParse(switchArg["--switch:".Length..], out bool switchValue)) | ||
| { | ||
| // Must be set before the first time the switch is read (first sorted AddRange). |

⚡ Quick start (run the demo)
From the repo root (e.g. C:\git\GitHub\WiseTechGlobal\winforms) - build the demo app
..dotnet\dotnet.exe build src\test\integration\WinformsControlsTest\WinformsControlsTest.csproj -c Debug
GUI: run the built app, then click "TreeView AddRange Order"
e.g. C:\git\GitHub\WiseTechGlobal\winforms\artifacts\bin\WinformsControlsTest\Debug\net10.0\WinFormsControlsTest.exe
What
Adds a minimal, self-contained repro to the WinForms demo app (WinformsControlsTest) that demonstrates a TreeView sort-order regression:
TreeNodeCollection.AddRangereverses the order of equal-comparing nodes whenTreeView.Sorted == true.This proves the issue is a framework/WinForms behavior, not application logic. Demo only — no product code is changed.
Scenario
TreeView.Sorted = truewith a customTreeViewNodeSorterwhoseComparealways returns0(i.e. several identically described items, e.g. empty pallets).TreeNodeCollection.AddRangein input orderPallet 1 .. Pallet 5.Pallet 1, Pallet 2, Pallet 3, Pallet 4, Pallet 5(stable).Pallet 5, Pallet 4, Pallet 3, Pallet 2, Pallet 1(reversed).How to reproduce
GUI: run
WinformsControlsTest→ click "TreeView AddRange Order". The form shows the input order, the result order, and whether it reversed.Add()-in-a-loop is provided as a stable contrast.Headless / scriptable:
The "Compare switch ON / OFF (child processes)" button runs all three in separate child processes and shows the captured output.
Does the AppContext switch fix it?
The
System.Windows.Forms.TreeNodeCollectionAddRangeRespectsSortOrderswitch (dotnet#11423) was suggested as a way to restore the old behavior. Empirically, in this exact build:true)--switch:true--switch:falseThe switch does not restore the order for the empty-parent + equal-nodes case: it only gates whether
FixedIndexis set, whileAddRangealways iterates the input array backwards. The reversal therefore needs an implementation-level fix (forward iteration on the sorted path), not just a runtime switch.Notes
TreeViewAddRangeOrderButton) is appended toMainFormControlsTabOrderto register the demo button.