dotnet/wpf · error · InvalidOperationException
SR.ReparentModelChildIllegal
Error message
SR.ReparentModelChildIllegal
What it means
InnerItemCollectionView refuses to add a model child (ItemsControl item that participates in the logical tree) which already has a logical parent. WPF throws InvalidOperationException('ReparentModelChildIllegal') because re-parenting an element into a second collection would corrupt the logical tree; the throw also doubles as a fast guard against adding the same element twice to the same collection.
Solutions
- Remove the item from its current logical parent before adding it (e.g. (prevParent as ItemsControl)?.Items.Remove(item), or detach from a Panel).
- Do not share a single element instance between two collections; create a new instance per collection.
- If the item should be moved, use a MVVM data-item collection (ItemsSource) instead of directly parenting UIElements so the container is generated per collection.
- Check for duplicate Add calls: verify the item is not already in the collection before adding.
Example fix
// before treeView2.Items.Add(node); // node still has logical parent treeView1 // after treeView1.Items.Remove(node); treeView2.Items.Add(node);
Defensive patterns
Strategy: validation
Validate before calling
bool canAdd = item is DependencyObject d && LogicalTreeHelper.GetParent(d) == null;
Type guard
static bool HasLogicalParent(object item) =>
item is DependencyObject d && LogicalTreeHelper.GetParent(d) != null; Try / catch
try { items.Add(node); }
catch (InvalidOperationException ex) when (ex.Message.Contains("parent")) { items.Remove(node); items.Add(node); } Prevention
- Never share UIElement instances across two ItemsControls; use data items + ItemsSource.
- Always Remove an element from its current parent before adding it elsewhere.
- Prefer MVVM data collections over directly parenting UIElements.
- Check LogicalTreeHelper.GetParent in debug asserts before Add calls.
When it happens
Trigger: Calling ItemsControl.Items.Add (or Remove followed by re-Add before the tree has detached the child) with a DependencyObject that still has LogicalTreeHelper.GetParent(node) != null, e.g. adding an element to two ItemsControls at once, or re-adding an item to the same collection without removing it first.
Common situations: Reusing UIElement instances across ItemsControls (e.g. moving a node between two TreeViews), adding an item that was declared as XAML content of another container, binding a collection containing elements already parented in the visual/logical tree, or a collection-change race where Remove has not yet detached the node.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- ' ' must be the root element of a tree, but has a logical…
- Cannot pass multidimensional array to the CopyTo method on…
- DoubleKeyFrameCollection
- Int16KeyFrameCollection
- Int32KeyFrameCollection
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/817dcf5d3e95e1c8.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/Controls/InnerItemCollectionView.cs:714
}
// check that item is not already parented
// throws an exception if already parented
private DependencyObject AssertPristineModelChild(object item)
{
DependencyObject node = item as DependencyObject;
if (node == null)
{
return null;
}
// refuse a child which already has a different model parent!
// NOTE: model tree spec would allow reparenting if the parent does not change
// but this code will throw: this is a efficient way to catch
// an attempt to add the same element twice to the collection
if (LogicalTreeHelper.GetParent(node) != null)
{
throw new InvalidOperationException(SR.ReparentModelChildIllegal);
}
return node;
}
// NOTE: Only change the item's logical links if the host is a Visual (bug 986386)
private void SetModelParent(object item)
{
// to avoid the unnecessary, expensive code in AddLogicalChild, check for DO first
if ((ModelParentFE != null) && (item is DependencyObject))
LogicalTreeHelper.AddLogicalChild(ModelParentFE, null, item);
}
// if item implements IModelTree, clear model parent
private void ClearModelParent(object item)
{
// ClearModelParent is also called for items that are not a DependencyObject;
// to avoid the unnecessary, expensive code in RemoveLogicalChild, check for DO first
if ((ModelParentFE != null) && (item is DependencyObject))View on GitHub (pinned to 81131a70a4)