A C# MVVM Service for displaying simple MessageBox messages with custom styles included - Uses MVVM Toolkit with Microsoft.Extensions.DependencyInjection but can be adapted to any MVVM / DI Library. This service illustrate how you can have a view model that displays dialog boxes but still can be easily unit tested.
In the example the MainViewModel is unit tested at 100% code coverage even with a complex path that display mutiple dialogs with various choices.
Include samples and an Example to unit test code involving a complex path with multiple MessageBoxes
This shows a function including multiple decisions triggered by user input. The Unit test module shows how to unit test the function for full code coverage.
WPF and .NET MAUI use the same platform-neutral contract from
Delange.MessageBox.Core:
IMessageDialogServiceMessageDialogRequestMessageDialogResultMessageDialogButtonsMessageDialogIcon
Both implementations expose ShowAsync, so view models and their unit tests can
be shared without referencing WPF or MAUI:
MessageDialogResult result = await dialogs.ShowAsync(
new MessageDialogRequest("Discard your changes?")
{
Title = "Confirm",
Buttons = MessageDialogButtons.YesNo,
Icon = MessageDialogIcon.Warning
});The platform implementations are named consistently:
Delange.MessageBox.Wpf.WpfMessageDialogServiceDelange.MessageBox.Maui.MauiMessageDialogService
MessageBox.Maui provides an asynchronous, MVVM-friendly abstraction over the
native .NET MAUI alert APIs for Android, iOS, Mac Catalyst, and Windows. It
supports OK, OK/Cancel, Yes/No, and Yes/No/Cancel dialogs, custom button labels,
cancellation while waiting, and serialized presentation.
Register the service in MauiProgram.CreateMauiApp:
builder.Services.AddMauiMessageDialogs();Inject and use it from a view model:
public sealed class EditorViewModel(IMessageDialogService dialogs)
{
public async Task<bool> ConfirmDiscardAsync(CancellationToken cancellationToken)
{
MessageDialogResult result = await dialogs.ShowAsync(
new MessageDialogRequest("Discard your unsaved changes?")
{
Title = "Confirm",
Buttons = MessageDialogButtons.YesNo,
Icon = MessageDialogIcon.Warning
},
cancellationToken);
return result == MessageDialogResult.Yes;
}
}The built-in implementation uses platform-native dialogs, so appearance follows
each operating system. MessageDialogIcon records intent for alternative/custom
presenters; native MAUI alerts do not guarantee a corresponding icon.
Run MessageBox.Maui.Sample to interactively test all button combinations and
walk through the same nine-path workflow demonstrated by the WPF sample.




