dotnet/wpf · error · InvalidOperationException

SR.ChildWindowMustHaveCorrectParent

Error message

SR.ChildWindowMustHaveCorrectParent

What it means

HwndHost.BuildWindow checks that the hosted HWND's parent is exactly the parent handle WPF passed in. If GetParent(_hwnd) does not match hwndParent, it throws InvalidOperationException (SR.ChildWindowMustHaveCorrectParent), enforcing that the child window was created with (or reparented to) the expected WPF parent.

Solutions

  1. Create the window with the hwndParent passed to BuildWindowCore as its parent.
  2. If wrapping an existing window, call SetParent(existingHwnd, hwndParent.Handle) before returning it.
  3. Check for third-party code re-parenting the window and remove or defer that reparenting.

Example fix

// before
protected override HandleRef BuildWindowCore(HandleRef parent) {
    return new HandleRef(this, CreateWindow(cls, IntPtr.Zero)); // NULL parent
}
// after
protected override HandleRef BuildWindowCore(HandleRef parent) {
    return new HandleRef(this, CreateWindow(cls, parent.Handle));
}
Defensive patterns

Strategy: validation

Validate before calling

if (UnsafeNativeMethods.GetParent(hwnd) != parent.Handle)
    UnsafeNativeMethods.SetParent(new HandleRef(null, hwnd), parent);

Type guard

bool HasExpectedParent(IntPtr child, IntPtr expectedParent) =>
    UnsafeNativeMethods.GetParent(child) == expectedParent;

Prevention

When it happens

Trigger: BuildWindowCore creates the window with a different/NULL parent, reparents the window after creation, or another component re-parents the HWND before HwndHost validation runs.

Common situations: Wrapping pre-existing native windows without calling SetParent, native libraries that re-parent their own windows, passing IntPtr.Zero as parent in custom CreateWindow calls.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Interop/HwndHost.cs:1024

            // Allow the derived class to build our HWND.
            _hwnd = BuildWindowCore(hwndParent);

            if(_hwnd.Handle == IntPtr.Zero || !UnsafeNativeMethods.IsWindow(_hwnd))
            {
                throw new InvalidOperationException(SR.ChildWindowNotCreated);
            }

            // Make sure that the window that was created is indeed a child window.
            int windowStyle = UnsafeNativeMethods.GetWindowLong(new HandleRef(this,_hwnd.Handle), NativeMethods.GWL_STYLE);
            if((windowStyle & NativeMethods.WS_CHILD) == 0)
            {
                throw new InvalidOperationException(SR.HostedWindowMustBeAChildWindow);
            }

            // Make sure the child window is the child of the expected parent window.
            if(hwndParent.Handle != UnsafeNativeMethods.GetParent(_hwnd))
            {
                throw new InvalidOperationException(SR.ChildWindowMustHaveCorrectParent);
            }

            // Test to see if hwndParent and _hwnd have different DPI_AWARENESS_CONTEXT's
            if (DpiUtil.GetDpiAwarenessContext(_hwnd.Handle) != DpiUtil.GetDpiAwarenessContext(hwndParent.Handle))
            {
                _hasDpiAwarenessContextTransition = true;
            }

            // Only subclass the child HWND if it is owned by our thread.
            int idWindowProcess;
            int idWindowThread = UnsafeNativeMethods.GetWindowThreadProcessId(_hwnd, out idWindowProcess);

#if WCP_SERVER2003_OR_LATER_ENABLED
            IntPtr hCurrentThread = UnsafeNativeMethods.GetCurrentThread();
            if ((idWindowThread == SafeNativeMethods.GetThreadId(hCurrentThread)) &&
                (idWindowProcess == UnsafeNativeMethods.GetProcessIdOfThread(hCurrentThread)))
#else
            if ((idWindowThread == SafeNativeMethods.GetCurrentThreadId()) &&

View on GitHub (pinned to 81131a70a4)