dotnet/wpf · error · InvalidOperationException

SR.WindowMustBeRoot

Error message

SR.WindowMustBeRoot

What it means

OnVisualParentChanged throws InvalidOperationException when a Window acquires a visual parent. A Window must always be the root of a visual tree; embedding one as a visual child of another element is unsupported. The check uses VisualTreeHelper.GetParent(this) != null.

Solutions

  1. Host embedded UI with UserControl or Page instead of Window.
  2. Show the second window as a separate top-level window (Show/ShowDialog) with an Owner set.
  3. If you need window-like chrome inside content, use a Border/Popup combination.

Example fix

// before
this.Content = new OtherWindow(); // Window as content
// after
this.Content = new OtherUserControl();
Defensive patterns

Strategy: validation

Validate before calling

bool safeToPresent(object content) => !(content is Window); // refuse Window as child content

Type guard

bool IsEmbeddableContent(object o) => o is UserControl || o is Page;

Prevention

When it happens

Trigger: Adding a Window instance into another element's visual/logical tree, e.g. panel.Children.Add(otherWindow) or via re-templating that places a Window as a child.

Common situations: Developers trying to embed windows as controls in a dashboard layout; code mistaking Window for a UserControl; XAML declaring a Window inside another Window's content.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/e62e160cd15ed485. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Window.cs:1777

            // Checking for Visual parent here covers all the scenarios
            // including the following:

            // Window w1 = new Window();
            // Window w2 = new WIndow();
            // w1.Show();
            // w2.Show();
            // w1.VisualChildren.Add(w2);


            // Window w1 = new Window();
            // Window w2 = new WIndow();
            // w1.Show();
            // w1.VisualChildren.Add(w2);
            //  w2.Show();

            if ( VisualTreeHelper.GetParent(this) != null )
            {
                throw new InvalidOperationException(SR.WindowMustBeRoot);
            }
        }

        /// <summary>
        ///     Measurement override. Implements content sizing logic.
        /// </summary>
        /// <remarks>
        ///     Deducts the frame size from the constraint and then passes it on
        ///     to its child.  Only supports one Visual child (just like control)
        /// </remarks>
        protected override Size MeasureOverride(Size availableSize)
        {
            VerifyContextAndObjectState();

            // Window content should respect Window's Max/Min size
            // setting in a SizeToContent Window.
            //
            // Take Min/Max[Width/Height] into consideration.  The logic here is similar to

View on GitHub (pinned to 81131a70a4)