Host registration
MVVMExpress uses Microsoft.Extensions.DependencyInjection only. There is no DryIoc, Unity, or Grace package. Shared libraries and tests call AddMvvmExpress. A MAUI app calls UseMvvmExpress, which registers Core services, replaces IMainThread with MauiMainThread, marshals command/property notifications, and auto-attaches ViewModelLifecycleBehavior.
builder
.UseMauiApp<App>()
.UseMvvmExpress(o => o
.UseNavigationPage()
.UseDialogs()
.UseAuth<LoginViewModel>());
// optional catalog path:
// .UseMvvmExpress(o => o.UseShell().UseDialogs().UseAuth<LoginViewModel>());
// net10.0 tests / shared ViewModel projects
services.AddMvvmExpress();
services.AddAuth<LoginViewModel>();UseNavigationPage is the login → replace-root → push host. UseShell is optional. UseDialogs lives in the Dialogs package. MvvmExpressOptions also has CancelOperationsOnDisappear, EnableDiagnostics, MarshalNotifications (default true), AutoAttachLifecycle, ConfirmDirtyNavigation, ForwardNavigationFailures, and ApplyGeneratedRegistrations. Call InitializeComponent() on App before resolving pages. Do not mix MAUI MainThread statics in ViewModels.
What AddMvvmExpress registers
| Abstraction | Default | Typical app replacement |
|---|---|---|
| IMessageHub | MessageHub | Keep |
| IBusyGate | BusyGate | Keep |
| IErrorSink | NullErrorSink | App logger sink |
| ICache / ICachedFetcher | MemoryCache / CachedFetcher | Plugin.Maui.ApiCache adapter |
| IConnectivityProbe | InMemoryConnectivityProbe | Plugin.Maui.NetworkMonitor adapter |
| IOperationExecutor | OperationExecutor | Keep |
| IViewModelScopeFactory | ServiceViewModelScopeFactory | Keep |
| IFeatureSwitch | MemoryFeatureSwitch | Plugin.Maui.FeatureFlags adapter |
| IStateStore | MemoryStateStore | App persist store |
| IWindowContext | WindowContext.Default | MauiWindowContext.Current |
| IWindowNavigatorRegistry | WindowNavigatorRegistry | Keep; register per window |
| INavigator / IPageNavigator | InMemoryNavigator | UseNavigationPage() / UseShell() |
| IMainThread | ImmediateMainThread | MauiMainThread (host) |
| IDialogs / INotifier | NullDialogs | UseDialogs() → MauiDialogs / MauiNotifier |
| IAuthState | not registered | UseAuth + Plugin.Maui.SecureSession adapter |
| IAccountService | not registered | App register / reset adapter |
Replace defaults in the MAUI host
UseNavigationPage / UseDialogs replace the in-memory defaults. UseAuth<TChallenge>() wraps GuardedNavigator when screens require a session — do not RemoveAll and reconstruct the guard. Do not register UseShell and UseNavigationPage together unless you really have two hosts.
builder.UseMvvmExpress(o => o
.UseNavigationPage((nav, _) => nav
.Map<LoginViewModel, LoginPage>("login")
.Map<ChatHostViewModel, ChatHostPage>("chats"))
.UseDialogs()
.UseAuth<AuthLoginViewModel>());
services.AddSingleton<IAuthState>(sp =>
new SecureSessionAuthState(sp.GetRequiredService<ISecureSession>()));
services.RemoveAll<IPageNavigator>();
services.AddSingleton<IPageNavigator>(sp =>
new MauiPageNavigator(MauiWindowContext.Current, sp)
.Map<PageStackViewModel, PageStackPage>("stack"));