dotnet/wpf · error · ArgumentException

SR.Visual_HasParent

Error message

SR.Visual_HasParent

What it means

Visual.AddVisualChild throws ArgumentException(SR.Visual_HasParent) when the child visual passed already has a parent. A Visual may only have one parent in the visual tree, so attaching an already-parented child is rejected.

Solutions

  1. Call RemoveVisualChild / remove from the old parent before adding to the new parent
  2. Create a new Visual instance instead of reusing one already in a tree
  3. Check Visual.Parent (or child._parent via VisualTreeHelper.GetParent) is null before adding

Example fix

// before
newParent.AddVisualChild(sharedChild);
// after
oldParent.RemoveVisualChild(sharedChild);
newParent.AddVisualChild(sharedChild);
Defensive patterns

Strategy: validation

Validate before calling

if (VisualTreeHelper.GetParent(child) != null) oldParent.RemoveVisualChild(child);

Type guard

bool IsUnparented(Visual c) => VisualTreeHelper.GetParent(c) == null;

Try / catch

try { parent.AddVisualChild(child); } catch (ArgumentException) { /* child already parented: detach and retry */ }

Prevention

When it happens

Trigger: Calling AddVisualChild (or re-parenting APIs) with a Visual that is currently attached to another parent without removing it first.

Common situations: Reusing visual instances across containers; forgetting RemoveVisualChild before re-adding; moving a child from one panel to another while it is still connected.

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/1471d163e2dea770. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Visual.cs:2579

        ///    method to find out where the child was added.
        ///
        ///  Remark: To move a Visual child in a collection it must be first disconnected and then connected
        ///    again. (Moving forward we might want to add a special optimization there so that we do not
        ///    unmarshal our composition resources).
        ///
        ///    It is okay to type this protected API to the 2D Visual.  The only 2D Visual with
        ///    3D childern is the Viewport3DVisual which is sealed.
        /// </summary>
        protected void AddVisualChild(Visual child)
        {
            if (child == null)
            {
                return;
            }

            if (child._parent != null)
            {
                throw new ArgumentException(SR.Visual_HasParent);
            }

            // invalid during a VisualTreeChanged event
            VisualDiagnostics.VerifyVisualTreeChange(this);

            SetFlags(true, VisualFlags.HasChildren);

            // Set the parent pointer.

            child._parent = this;

            //
            // The child might be dirty. Hence we need to propagate dirty information
            // from the parent and from the child.
            //

            Visual.PropagateFlags(
                this,

View on GitHub (pinned to 81131a70a4)