lepoco/wpfui · error · InvalidOperationException

Only one ContentDialogHost instance is allowed per Window.

Error message

Only one ContentDialogHost instance is allowed per Window.

What it means

Thrown by ContentDialogHost.RegisterHost when a second, distinct ContentDialogHost instance tries to register itself for the same Window. The library keeps a single-slot-per-window map (WindowHosts) because only one host can own the overlay layer for a window; registering a different instance is treated as a programming error rather than silently replacing the first.

Source

Thrown at src/Wpf.Ui/Controls/ContentDialog/ContentDialogHost.cs:220

    private void RegisterHostForWindow()
    {
        var window = Window.GetWindow(this);
        if (window != null)
        {
            RegisterHost(window);
        }
    }

    private void RegisterHost(Window window)
    {
        lock (WindowHostsLock)
        {
            if (WindowHosts.TryGetValue(window, out var existing))
            {
                if (!ReferenceEquals(existing, this))
                {
                    throw new InvalidOperationException(
                        "Only one ContentDialogHost instance is allowed per Window."
                    );
                }

                // already registered for this window and it's this instance
                return;
            }

            WindowHosts.Add(window, this);
        }
    }
}

#pragma warning restore IDE0008 // Use explicit type instead of 'var'

View on GitHub (pinned to ffebacd610)

Solutions

  1. Keep exactly one ContentDialogHost per Window — typically at the root of the window's content.
  2. If you need hosts in multiple user controls, remove the duplicates and let them share the window-level host.
  3. Ensure the previous host is properly unloaded (removed from the visual tree) before adding a new one.
  4. Check WindowHosts registrations during debugging if you suspect a stale entry.

Example fix

<!-- before -->
<Window>
  <StackPanel>
    <ui:ContentDialogHost x:Name="host1"/>
    <ui:ContentDialogHost x:Name="host2"/> <!-- throws on load -->
  </StackPanel>
</Window>

<!-- after -->
<Window>
  <ui:ContentDialogHost x:Name="host"/>
</Window>
Defensive patterns

Strategy: validation

Validate before calling

// In a window, ensure only one host exists
var hosts = FindVisualChildren<ContentDialogHost>(this).ToList();
Debug.Assert(hosts.Count <= 1, $"{hosts.Count} ContentDialogHosts in window");

Prevention

When it happens

Trigger: Placing two <ui:ContentDialogHost> elements in the same Window's visual tree; adding a second host dynamically after one is already loaded; re-hosting on a window that still holds a previously-loaded host that was never unloaded.

Common situations: Migrating an app to WPF UI and leaving an old ContentDialogHost in XAML while adding another in a user control that lives in the same window; merging two user controls each of which ships its own host into one window; a host whose Unloaded handler did not fire (e.g. window closed via ShutdownMode) leaving a stale registration.

Related errors


AI-assisted analysis of lepoco/wpfui@ffebacd610 (2026-08-13). Data as JSON: /api/errors/227ae3fd6d172f65. Report an issue: GitHub.