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

  1. Remove the item from its current logical parent before adding it (e.g. (prevParent as ItemsControl)?.Items.Remove(item), or detach from a Panel).
  2. Do not share a single element instance between two collections; create a new instance per collection.
  3. 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.
  4. 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

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


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)