Application framework
MVVMExpress
Modular MVVM for MAUI — ViewModels, async state, Shell or NavigationPage, dialogs
Current NuGet 1.3.0
A modular MVVM framework for .NET MAUI on Android, iOS, Mac Catalyst, and Windows (single-window): observable models, async commands, bindable AsyncState, lifecycle-aware cancellation, typed Shell or NavigationPage navigation, dialogs, toast, validation, pagination, forms, Reactive, and source generators. 1.3.0 ships Phases 8–10 on the 1.0 SemVer lock — one registration path, analyzers, modules, modal stack, sibling host adapters, SectionHostView, MvvmSearch, and ILLink roots.
Install
dotnet add package Plugin.Maui.MVVMExpress.Core
dotnet add package Plugin.Maui.MVVMExpressPackage IDs: Plugin.Maui.MVVMExpress.CorePlugin.Maui.MVVMExpress
Plugin.Maui.* restores from GitHub Packages. Add the org feed first — see Use nuvyntralabs GitHub Packages from a C# project.
Or scaffold an app
dotnet new install Plugin.Maui.MVVMExpress.Templates
dotnet new mvvmexpress -n MyAppAdds MainPage + MainPageViewModel, login replace-root, a list, a form, and tests. Then dotnet new mvvmexpress-page -n Catalog --namespace MyApp. Same commands from the VS Code and Visual Studio extensions.
Overview
MVVMExpress is the application shell for production MAUI apps on Android, iOS, Mac Catalyst, and Windows (single-window). CommunityToolkit.Mvvm covers properties and commands, Prism.Maui covers page navigation (not Shell), and ReactiveUI covers observable pipelines. A field or enterprise app often needs all three plus bindable async state, lifecycle-aware cancellation, and typed navigation — without taking three overlapping frameworks. Core targets net10.0 and does not reference MAUI. Current NuGet is 1.3.0: Phases 8–10 on the 1.0 SemVer lock. Scaffold with Plugin.Maui.MVVMExpress.Templates (dotnet new mvvmexpress / mvvmexpress-page), or install the MVVMExpress listings on the Visual Studio Code and Visual Studio Marketplaces — the extensions pin the same 1.3.0 pack. 1.0.0 remains the SemVer lock: UseAuth<TChallenge>() wraps GuardedNavigator, pages are constructed on IMainThread, UseNavigationPage and UseShell are equal hosts, generated [RegisterView] maps apply without a required Map callback, SectionHostView binds tabs in place, and SnapshotCollection loads a list once. Capability work (captive portal, HTTP cache, offline sync, form XAML, flags, deep links) stays in focused MauiEssentials plugins on Android and iOS; UseDeepLinks and UseSecureSessionAuth compose them and fail closed if the sibling is missing.
Current release
- 1.3.0. Phases 8–10. One registration path, [NotifyDependsOn], analyzers, CommunityToolkit ViewModel interop, IModule / AddModule, modal stack, UseDeepLinks / UseSecureSessionAuth, SectionHostView, MvvmSearch, ILLink roots, 1.0 contract tests.
- Templates and Marketplace IDE wrappers pin Plugin.Maui.MVVMExpress.Templates 1.3.0.
- 1.0.0 remains the SemVer lock. Public 1.x APIs stay source-compatible. Breaking changes wait for 2.0.0.
Capabilities
- ObservableModel, ViewModel lifecycle, and ViewModelCancellationToken cancelled on dispose.
- Sync and async commands with UI-thread marshal, weak CanExecuteChanged, no-throw ICommand.Execute, timeout, retry, debounce, and throttle.
- Host / Navigation / Dialogs on Android, iOS, Mac Catalyst, and Windows (single-window). Sibling adapters stay Android + iOS.
- UseNavigationPage + ResetAsync / ReplaceRootAsync (replaces window.Page with a NavigationPage). UseShell is an equal host for flyout, tabs, and // routes.
- Navigators hop to IMainThread before new Page() or Shell.GoToAsync. Off-thread factories throw. PushModalAsync / PopModalAsync on IPageNavigator.
- SectionHostView + SectionHostViewModel in-place tabs, SnapshotCollection load-once lists, MvvmSearch + SearchQuery.CommittedText.
- FormViewModel.Bind, dirty confirm, SubmitAsync, MustMatch, undo/redo.
- UseAuth<TChallenge>() / AddAuth<TChallenge>() wraps GuardedNavigator. UseSecureSessionAuth() is the production adapter (fail closed).
- UseDeepLinks() maps a URI onto INavigator, [Route], and the auth challenge. Missing sibling throws.
- MauiNotifier toast via Window.AddOverlay — never wraps Page.Content.
- [Notify], [NotifyDependsOn], [RegisterView] page maps, ModuleInitializer routes, [PersistState], and [RequiresAuth].
- IModule / AddModule<T>() for feature-team registration. Convention scan is not a supported 1.3 path (MVVME010).
- Analyzers MVVME001–003 and MVVME010–013 in the SourceGenerators pack.
- CoalescingDispatcher for inbox / hub handlers. IMainThread is the only marshal API in ViewModels.
- Testing package: LeakProbe (including Button + pop page), ScaleProfile, FakeDialogs, FakeNavigator, ScopedNavigator, 1.0 Contract.Tests.
- Adapters for NetworkMonitor, ApiCache, OfflineSync, SecureSession, FormValidation, FeatureFlags, and DeepLinks.
- dotnet new mvvmexpress and mvvmexpress-page via Plugin.Maui.MVVMExpress.Templates.
- VS Code (Create New App / Add Page) and Visual Studio 2022+ (Tools → MVVMExpress; File → New → Project) Marketplace wrappers.
Documentation
Documentation
ViewModels, commands, DI, messaging, NavigationPage or Shell, modules, chat host, forms, generators, analyzers, project template, IDE extensions, and the shipped 1.3.0 roadmap.
Getting started
dotnet new mvvmexpress, VS Code or Visual Studio Marketplace extensions, install 1.3.0 into an existing app, first screen, UseNavigationPage vs UseShell, Playground clone, FakeNavigator / LeakProbe, forms, generators, and adapters.
Comparison
Surfaces, syntax map ([Notify] vs [ObservableProperty], INavigator vs INavigationService), trade-offs, and when to choose each.
IDE extensions
Install the MVVMExpress listings on the Visual Studio Code and Visual Studio Marketplaces. Thin wrappers that install the template pack and run dotnet new.
Playground sample
Cloneable 15-minute path in the product repo — command, navigation, dialog, form, auth, and list. Not a separate SampleApp repository.
Package family
| Package | Purpose | Status |
|---|---|---|
| Plugin.Maui.MVVMExpress.CoreGitHub Packagesnuget.org | Observable model, commands, ViewModel, SectionHost, IModule, navigator/cache/auth abstractions, state, outcome, messaging | Implemented + tests |
| Plugin.Maui.MVVMExpressGitHub Packagesnuget.org | UseMvvmExpress, UseAuth, UseDeepLinks, UseSecureSessionAuth, MauiMainThread, SectionHostView, MvvmSearch, auto lifecycle, BusyOverlayBehavior, AsyncStateView | Implemented |
| Plugin.Maui.MVVMExpress.NavigationGitHub Packagesnuget.org | MauiShellNavigator + MauiPageNavigator, UseNavigationPage / UseShell, replace-root, PushModalAsync / PopModalAsync | Implemented + tests |
| Plugin.Maui.MVVMExpress.DialogsGitHub Packagesnuget.org | IDialogs + MauiDialogs + MauiNotifier (Window.AddOverlay toast) | Implemented + tests |
| Plugin.Maui.MVVMExpress.ValidationGitHub Packagesnuget.org | DataAnnotations + IValidator + MustMatch + ILLink trim roots | Implemented + tests |
| Plugin.Maui.MVVMExpress.PaginationGitHub Packagesnuget.org | PagedCollection<T>, SnapshotCollection<T>, SearchQuery.CommittedText, CollectionBind.AsyncFetch | Implemented + tests |
| Plugin.Maui.MVVMExpress.TestingGitHub Packagesnuget.org | LeakProbe, ScaleProfile, FakeDialogs, FakeNavigator, FakeMainThread, FakeConnectivity, FakeMessageHub, ScopedNavigator | Implemented + tests |
| Plugin.Maui.MVVMExpress.ReactiveGitHub Packagesnuget.org | IPropertyObservable / CombineLatest — no System.Reactive required | Implemented + tests |
| Plugin.Maui.MVVMExpress.SourceGeneratorsGitHub Packagesnuget.org | [Notify], [NotifyDependsOn], commands, register, routes, persist, auth, MVVME001–013 analyzers | Implemented + snapshot tests |
| Plugin.Maui.MVVMExpress.Compatibility.CommunityToolkitGitHub Packagesnuget.org | CommunityToolkitMessageHub plus ObservableObject ViewModel interop (INavigator / IDialogs) | Implemented + tests |
| Plugin.Maui.MVVMExpress.TemplatesGitHub Packagesnuget.org | dotnet new mvvmexpress (app) and mvvmexpress-page (XAML + ViewModel + service) | Implemented |
Compose with
- Plugin.Maui.NetworkMonitorValidated internet versus captive portal for IConnectivityProbe.
- Plugin.Maui.HttpForgeSource-generated typed REST client from ViewModels — compose with ApiResilience / ApiCache.
- Plugin.Maui.ApiCacheHTTP GET CacheFirst / SWR behind ICache.
- Plugin.Maui.LocalStoreRoom-style local CRUD — host picks SQLite, NuvexaDB, or another engine.
- Plugin.Maui.OfflineSyncLocal writes and queued sync — not a database inside MVVMExpress.
- Plugin.Maui.SecureSessionTokens and 401 refresh for IAuthState / GuardedNavigator.
- Plugin.Maui.FormValidationXAML Validation.For next to IValidator.
- Plugin.Maui.FeatureFlagsIFeatureSwitch adapter for rollouts.
- Plugin.Maui.DeepLinksApp Links / Universal Links into INavigator route + query.
- Plugin.Maui.PermissionFlowIPermissionGate adapter for permission UX.
- Plugin.Maui.DiagnosticsANR / crash breadcrumbs next to EnableDiagnostics in Debug.
- Plugin.Maui.LeakAnalyserRuntime visual-tree leak detection after pop — complementary to LeakProbe unit tests.
- Plugin.Maui.KeyboardManagerKeyboard pan / safe area / dismiss for chat composers.
- .NET MAUI
- MVVM
- ViewModel
- C#
- Mac Catalyst
- Windows
- VS Code
- Visual Studio
Discussion
Comment on Plugin.Maui.MVVMExpress. The thread lives on this component's GitHub repository (nuvyntralabs/Plugin.Maui.MVVMExpress). Sign in with GitHub — Giscus uses Discussions, Utterances uses Issues.