Skip to content
Nuvyntra Labs

Documentation

Introduction

What WPF MVVMExpress is, why it exists, the MIT license, design principles, and how these docs are organized.

Status

Product name is MVVMExpress (WPF family). Package prefix is Plugin.Wpf.MVVMExpress. Core does not reference System.Windows or Microsoft.Maui.Controls. Manual INotifyPropertyChanged and hand-written commands are first-class. There is no Shell host — put a Frame named NavigationHost in the window.

License

WPF MVVMExpress is MIT licensed. There is no community-versus-commercial split and no revenue threshold. You may use the packages in commercial apps without a paid framework license. The SPDX identifier is MIT; LICENSE lives at the repository root and is packed with each nupkg.

That is a product choice, not a jab at other frameworks. If you already pay for a commercial MVVM stack, keep it. This family exists so a WPF team can take ViewModels, async state, and Frame navigation without a second license conversation — and so a MAUI team already on Plugin.Maui.MVVMExpress can keep the same Core contract on desktop.

Why this exists

A production WPF app needs more than INotifyPropertyChanged and ICommand: ViewModel lifecycle bound to Loaded / Unloaded, async work with cancellation, timeout, retry, and busy state, strongly typed Frame navigation, UI state richer than a boolean IsBusy, and testable ViewModels with no static MessageBox or Frame calls.

  • CommunityToolkit.Mvvm covers properties, commands, and messaging.
  • Prism covers region and URI navigation. It is a different composition model.
  • Caliburn.Micro covers convention-based screens and conductors.
  • ReactiveUI covers observable pipelines and activation, and requires System.Reactive.

None of those, alone, is a WPF-first operation + state + Frame-journal framework with the same Core contract as the MAUI family. MVVMExpress is that shell for desktop. It is not a fork of those libraries and it is not a MAUI package wearing a WPF TFM.

Design principles

  1. Core is UI-framework-free. Plugin.Wpf.MVVMExpress.Core must not reference System.Windows or Microsoft.Maui.Controls.
  2. Optional means optional. Navigation, dialogs, validation, pagination, and testing are separate packages.
  3. Interfaces at the ViewModel boundary. ViewModels depend on INavigator, IDialogs, IMainThread — never on MessageBox, Frame, or Dispatcher.CurrentDispatcher statics.
  4. Async-first, cancellation-first. Every public async API accepts CancellationToken.
  5. No hidden global state. No static service locator in Core.
  6. One navigator per Window. IWindowContext / WindowNavigatorRegistry key navigation, dialogs, and scopes by window — not Application.Current.MainWindow.
  7. No Shell. Frame + SectionHostViewModel cover stack navigation and in-place tabs.
  8. Do not silently swallow exceptions. Every catch transforms to Outcome, calls IErrorSink, logs and rethrows, or maps OperationCanceledException to Cancelled.
  9. No PackageReference to Plugin.Maui.MVVMExpress.*. A ViewModel ports with a namespace swap, not a shared assembly.

How to read these docs

The left nav follows the surfaces a production WPF app actually touches. Start here for the contract. Getting started is the scaffold-or-install path, including dotnet new wpf-mvvmexpress, the first screen, and the Playground clone. Project template documents the packed templates. IDE extensions covers the Visual Studio Code and Visual Studio Marketplace wrappers. Comparison evaluates CommunityToolkit.Mvvm, Prism, Caliburn.Micro, and ReactiveUI. Application model covers ViewModels, commands, DI, and messaging. Application shell covers Frame navigation, chat host, dialogs, validation, forms, and lists. Composition and internals explain packages, windows, the operation pipeline, tests, and scale. Release covers the shipped 1.0.0 roadmap and what waits for a later version.

  • Shipped in 1.0.0 means types exist and tests exist. Frame navigation, dialogs, validation, pagination, templates, and IDE wrappers are complete.
  • This is not Plugin.Maui.MVVMExpress. Do not add a PackageReference to Plugin.Maui.MVVMExpress.*. A ViewModel ports with a namespace swap.
  • Source generators, Reactive, Shell, UseDeepLinks, and UseSecureSessionAuth are out of 1.0 — see the roadmap.
  • Type names stay unique so CommunityToolkit.Mvvm or Prism can sit in the same app if you need them.

Naming — no collisions

Core type names must not collide with CommunityToolkit.Mvvm or Prism when both are referenced.

ConceptMVVMExpressAvoid copying
Observable baseObservableModelObservableObject
ViewModel baseViewModel / PageViewModelPrism BindableBase / Screen
Sync commandModelCommandRelayCommand, DelegateCommand
Async commandAsyncModelCommandAsyncRelayCommand, ReactiveCommand
MessengerIMessageHubIMessenger, IEventAggregator
NavigationINavigatorINavigationService, IWindowManager
DialogsIDialogsIDialogService, MessageBox.Show
Parameterstyped records / IAcceptNavArgs<T> / IAcceptNavQueryINavigationParameters
ResultOutcome / Outcome<T>competing Result<T> packages

Feature comparison

Designed product surface against CommunityToolkit.Mvvm, Prism (WPF), Caliburn.Micro, and ReactiveUI. This table does not claim MVVMExpress is faster than the others. Shipping versus designed is tracked in the repository API-PARITY.md.

FeatureMVVMExpressCommunityToolkit.MvvmPrismReactiveUI
Observable propertiesYes (hand-written in 1.0)YesYesYes
Commands / async commandsYesYesYes / PartialYes
Source generatorsOut of 1.0YesNoYes
Navigation (Frame)Yes (Frame + owned-window modal)NoYes (regions / URI)Yes
Lifecycle + cancellationYesNoYesYes
Dialogs / toastYes (MessageBox + AdornerLayer)SeparateYesExtensions
ValidationYesYesExtensionsYes
Reactive derived stateOut of 1.0NoNoYes (Rx required)
Pagination + searchYesNoExtensionsExtensions
Unified AsyncState<T>YesNoNoExtensions
Typed navigation record argsYesNoNo (dictionary / URI)Partial
Multi-windowYes (IWindowContext per Window)App-ownedYesPartial
Memory-leak GC testsYes (VM, command, pop, messenger)PartialPartialPartial
Testing packageYesPartialYesYes

Discussion

Comment on Plugin.Wpf.MVVMExpress. The thread lives on this component's GitHub repository (nuvyntralabs/Plugin.Wpf.MVVMExpress). Sign in with GitHub — Giscus uses Discussions, Utterances uses Issues.