lepoco/wpfui · error · InvalidOperationException

Cannot change DialogHostEx while the dialog is being shown.

Error message

Cannot change DialogHostEx while the dialog is being shown.

What it means

Thrown by the ContentDialog.DialogHostEx setter when you attempt to reassign the host while a previous ShowAsync call is still in flight. The dialog tracks an IsShowing flag (Tcs != null and not completed) and refuses host mutations mid-display to avoid tearing down the visual tree under a live await. It is a state-machine guard, not a data error.

Source

Thrown at src/Wpf.Ui/Controls/ContentDialog/ContentDialog.cs:679

    /// </summary>
    /// <exception cref="InvalidOperationException">
    /// Thrown if trying to set DialogHostEx when DialogHost is already set, or if trying to change DialogHostEx while the dialog is being shown.
    /// </exception>
    public ContentDialogHost? DialogHostEx
    {
        get => _dialogHostEx;
        set
        {
            if (_dialogHost is not null)
            {
                throw new InvalidOperationException(
                    "Cannot set DialogHostEx when DialogHost is already set."
                );
            }

            if (IsShowing)
            {
                throw new InvalidOperationException(
                    "Cannot change DialogHostEx while the dialog is being shown."
                );
            }

            if (!ReferenceEquals(_dialogHostEx, value))
            {
                _dialogHostEx = value;
            }

            UpdateIsLegacyHost();
        }
    }

    [Obsolete("ContentPresenter is deprecated. Please use DialogHost instead.")]
    public ContentPresenter? ContentPresenter { get; set; } = default;

    protected TaskCompletionSource<ContentDialogResult>? Tcs { get; set; }

View on GitHub (pinned to ffebacd610)

Solutions

  1. Await the previous ShowAsync() call to completion before assigning DialogHostEx.
  2. Set DialogHostEx once at construction / XAML time and do not rebind it.
  3. If you must swap hosts, create a new ContentDialog instance per host rather than mutating the existing one.
  4. Guard the assignment yourself: if (!dialog.IsShowing) dialog.DialogHostEx = host; — note IsShowing is private, so track the ShowAsync task yourself.

Example fix

// before
_ = dialog.ShowAsync();
dialog.DialogHostEx = otherHost; // throws

// after
await dialog.ShowAsync();
dialog.DialogHostEx = otherHost;
Defensive patterns

Strategy: validation

Validate before calling

// Track the in-flight task yourself (IsShowing is private)
private Task<ContentDialogResult>? _showTask;

if (_showTask is null || _showTask.IsCompleted)
    dialog.DialogHostEx = newHost;
else
    Debug.WriteLine("Cannot change DialogHostEx: dialog is showing.");

Prevention

When it happens

Trigger: Assigning dialog.DialogHostEx = newHost while the Task returned by a prior dialog.ShowAsync() has not yet completed (i.e. the dialog is still on screen or the TCS is pending). Also fires if a binding pushes a new value to DialogHostEx during display.

Common situations: Reusing a single ContentDialog instance across windows and swapping the host in a view-model; data-binding DialogHostEx to a property that changes on navigation; calling ShowAsync without await and immediately reassigning the host.

Related errors


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