.NET version
We verified the failure on .NET 6.0, .NET 8.0, .NET 10.0, and the current .NET 11 main branch at commit 8efd9a920dba90722f8db1f7e943f74837d26579 from 2026-09-10. The same scenario is clean on .NET Framework 4.7.2, .NET Core 3.1, and .NET 5.0.
Did it work in .NET Framework?
Yes. We confirmed the behavior is correct on .NET Framework 4.7.2, where the TreeView fills in normally and no exception is raised.
Did it work in any of the earlier releases of .NET Core or .NET 5+? If so, which version?
Yes. We checked the earlier releases and confirmed the same code path works on .NET Core 3.1 and .NET 5.0. The first failing release is .NET 6.0.
Issue description
When we swap items through the indexed setter on a TreeNode's Nodes collection (nodes[i] = nodes[j]), the in-place sort throws NullReferenceException if that node has never been attached to a TreeView. The exception is raised by System.Windows.Forms.TreeNodeCollection.set_Item(Int32, TreeNode).
The current implementation reads the owning node's TreeView into a local without checking for null, then dereferences it while checking whether the handle is already present. In a detached node, _owner._treeView is null, which makes this fail before the collection ever has a parent view. The relevant code is here:
|
TreeView tv = _owner._treeView!; |
|
TreeNode actual = _owner._children[index]; |
|
|
|
if (value._treeView is not null && value._treeView.Handle != tv.Handle) |
|
{ |
|
throw new ArgumentException(string.Format(SR.TreeNodeBoundToAnotherTreeView), nameof(value)); |
|
} |
|
|
|
if (tv._nodesByHandle.ContainsKey(value.Handle) && value._index != index) |
This regression appears to have been introduced by #4297, which was merged on 2020-12-05 to stop a node from being added twice. The new TreeView/nodesByHandle validation was added there, but it did not guard the detached-owner case. See: #4297
The same code path is present on release/6.0 and absent on release/5.0, which matches the observed version split. Relevant references:
We also observed a second, distinct exception when the parent node is attached to a TreeView before the same swap-based reorder is attempted. In a minimal console harness on .NET 6, .NET 8, and .NET 10, the reorder throws ArgumentException: Cannot add or insert the item '2' in more than one place. You must first remove it from its current location or clone it. from the same indexed setter. This is the duplicate-node check added in the same PR (SR.OnlyOneControl), and it rejects the transient intermediate state created by the swap idiom. We observed this in a bare console reproduction rather than in a fully created Form/TreeView scenario, so we describe it as observed behavior rather than assuming it is the only valid workaround.
Steps to reproduce
No Form or TreeView is required to make this fail. A console app that references System.Windows.Forms with UseWindowsForms reproduces it in the same way, because the exception happens before the node is connected to any tree.
using System.Windows.Forms;
var parentNode = new TreeNode("a");
parentNode.Nodes.Add(new TreeNode("3"));
parentNode.Nodes.Add(new TreeNode("2"));
parentNode.Nodes.Add(new TreeNode("1"));
Sort(parentNode.Nodes); // throws NullReferenceException on .NET 6+
static void Sort(TreeNodeCollection nodes)
{
for (int i = 0; i < nodes.Count; i++)
{
for (int j = i + 1; j < nodes.Count; j++)
{
if (StringComparer.Ordinal.Compare(nodes[i].Text, nodes[j].Text) > 0)
{
TreeNode temp = nodes[i];
nodes[i] = nodes[j];
nodes[j] = temp;
}
}
}
}
- Create a
TreeNode and populate its child nodes without attaching the parent to a TreeView.
- Reorder the children by assigning through the indexer (
nodes[i] = nodes[j]).
- Observe the
NullReferenceException on .NET 6.0 and later. This does not happen on .NET Framework 4.7.2, .NET Core 3.1, or .NET 5.0.
Expected Behavior (Before .NET 6)

.NET version
We verified the failure on .NET 6.0, .NET 8.0, .NET 10.0, and the current .NET 11 main branch at commit
8efd9a920dba90722f8db1f7e943f74837d26579from 2026-09-10. The same scenario is clean on .NET Framework 4.7.2, .NET Core 3.1, and .NET 5.0.Did it work in .NET Framework?
Yes. We confirmed the behavior is correct on .NET Framework 4.7.2, where the
TreeViewfills in normally and no exception is raised.Did it work in any of the earlier releases of .NET Core or .NET 5+? If so, which version?
Yes. We checked the earlier releases and confirmed the same code path works on .NET Core 3.1 and .NET 5.0. The first failing release is .NET 6.0.
Issue description
When we swap items through the indexed setter on a
TreeNode'sNodescollection (nodes[i] = nodes[j]), the in-place sort throwsNullReferenceExceptionif that node has never been attached to aTreeView. The exception is raised bySystem.Windows.Forms.TreeNodeCollection.set_Item(Int32, TreeNode).The current implementation reads the owning node's
TreeViewinto a local without checking for null, then dereferences it while checking whether the handle is already present. In a detached node,_owner._treeViewis null, which makes this fail before the collection ever has a parent view. The relevant code is here:winforms/src/System.Windows.Forms/System/Windows/Forms/Controls/TreeView/TreeNodeCollection.cs
Lines 45 to 53 in 8efd9a9
This regression appears to have been introduced by #4297, which was merged on 2020-12-05 to stop a node from being added twice. The new
TreeView/nodesByHandlevalidation was added there, but it did not guard the detached-owner case. See: #4297The same code path is present on
release/6.0and absent onrelease/5.0, which matches the observed version split. Relevant references:We also observed a second, distinct exception when the parent node is attached to a
TreeViewbefore the same swap-based reorder is attempted. In a minimal console harness on .NET 6, .NET 8, and .NET 10, the reorder throwsArgumentException: Cannot add or insert the item '2' in more than one place. You must first remove it from its current location or clone it.from the same indexed setter. This is the duplicate-node check added in the same PR (SR.OnlyOneControl), and it rejects the transient intermediate state created by the swap idiom. We observed this in a bare console reproduction rather than in a fully createdForm/TreeViewscenario, so we describe it as observed behavior rather than assuming it is the only valid workaround.Steps to reproduce
No
FormorTreeViewis required to make this fail. A console app that referencesSystem.Windows.FormswithUseWindowsFormsreproduces it in the same way, because the exception happens before the node is connected to any tree.TreeNodeand populate its child nodes without attaching the parent to aTreeView.nodes[i] = nodes[j]).NullReferenceExceptionon .NET 6.0 and later. This does not happen on .NET Framework 4.7.2, .NET Core 3.1, or .NET 5.0.Expected Behavior (Before .NET 6)