lepoco/wpfui · error · InvalidOperationException

Use {nameof(Close)} with MessageBoxResult instead

Error message

Use {nameof(Close)} with MessageBoxResult instead

What it means

MessageBox.Close() (the no-arg Window method) is hidden and hard-throws because closing a WPF UI MessageBox requires passing a MessageBoxResult so the internal TaskCompletionSource resolves with the user's choice. Calling the parameterless Close would shut the window without setting a result, leaving awaiters of ShowDialogAsync hanging — so the library forbids it.

Source

Thrown at src/Wpf.Ui/Controls/MessageBox/MessageBox.cs:297

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

    [Obsolete($"Use {nameof(ShowDialogAsync)} instead")]
    public new void Show()
    {
        throw new InvalidOperationException($"Use {nameof(ShowDialogAsync)} instead");
    }

    [Obsolete($"Use {nameof(ShowDialogAsync)} instead")]
    public new bool? ShowDialog()
    {
        throw new InvalidOperationException($"Use {nameof(ShowDialogAsync)} instead");
    }

    [Obsolete($"Use {nameof(Close)} with MessageBoxResult instead")]
    public new void Close()
    {
        throw new InvalidOperationException($"Use {nameof(Close)} with MessageBoxResult instead");
    }

    /// <summary>
    /// Displays a message box
    /// </summary>
    /// <returns><see cref="MessageBoxResult"/></returns>
    /// <exception cref="TaskCanceledException">Thrown if the operation is canceled.</exception>
    public async Task<MessageBoxResult> ShowDialogAsync(
        bool showAsDialog = true,
        CancellationToken cancellationToken = default
    )
    {
        Tcs = new TaskCompletionSource<MessageBoxResult>();
        CancellationTokenRegistration tokenRegistration = cancellationToken.Register(
            o => Tcs.TrySetCanceled((CancellationToken)o!),
            cancellationToken
        );

View on GitHub (pinned to ffebacd610)

Solutions

  1. Call messageBox.Close(MessageBoxResult.Ok) (or the appropriate result) so the TCS resolves.
  2. In a generic 'close all windows' routine, special-case MessageBox and pass a default result.
  3. Prefer letting the box's own buttons close it; only close programmatically with an explicit result.
  4. If you must force-close without a result, cancel the ShowDialogAsync CancellationToken instead.

Example fix

// before
var box = new MessageBox { Content = "hi" };
box.Close(); // throws

// after
var box = new MessageBox { Content = "hi" };
box.Close(MessageBoxResult.Ok);
Defensive patterns

Strategy: validation

Validate before calling

// Always pass a result when closing programmatically:
box.Close(MessageBoxResult.Ok);

Prevention

When it happens

Trigger: Calling messageBox.Close() (no args) on a WPF.UI MessageBox; auto-close logic that calls Close() on any open Window; a 'close all windows' routine that walks the window list.

Common situations: A 'close everything on logout' helper; user code that closes the box from a non-button handler; migration from classic MessageBox where Close() was used to dismiss; CI/automation that dismisses windows generically.

Related errors


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