Table of Contents

MVVM Pattern

Binding Modes

Mode XAML View ViewModel
View-first ViewModelLocator.AutoWireViewModel="True" XAML / DI shell / new From DI
ViewModel-first ContentControl Content="{Binding Vm}" ViewLocator creates From DI

Registration

AddMvvmTransient / AddMvvmSingleton register ViewModel in DI and record View mapping only:

services.AddMvvmTransient<MainView, MainViewModel>();
services.AddMvvmSingleton<AboutView, AboutViewModel>();

Shell views (MainWindow, etc.) are not in DI — use CreateShell:

CreateShell<MainWindow, MainView>();

ILifecycleAware (Optional)

Implement on ViewModel for automatic OnLoadedAsync / OnUnloaded:

public partial class MainViewModel : ObservableObject, ILifecycleAware
{
    public Task OnLoadedAsync() => LoadDataAsync();
    public Task OnUnloaded() => SaveStateAsync();
}

Tab / WebView: OnUnloaded fires when leaving visual tree — manage caching in your app if needed.

API Summary

API Description
AddMvvmTransient<TView, TViewModel>() AddTransient<TViewModel>() + mapping
AddMvvmSingleton<TView, TViewModel>() AddSingleton<TViewModel>() + mapping
CreateShell<TWindow, TView>() Create shell with new by platform lifetime
ILifecycleAware Optional load/unload hooks

Further Reading

How it works: Architecture — MVVM Wiring — ViewModelLocator vs ViewLocator, mapping dictionaries, and lifecycle binding. Design Decisions — why View is not in DI.