NuExt.Minimal.Mvvm.Wpf
0.7.3
Prefix Reserved
dotnet add package NuExt.Minimal.Mvvm.Wpf --version 0.7.3
NuGet\Install-Package NuExt.Minimal.Mvvm.Wpf -Version 0.7.3
<PackageReference Include="NuExt.Minimal.Mvvm.Wpf" Version="0.7.3" />
<PackageVersion Include="NuExt.Minimal.Mvvm.Wpf" Version="0.7.3" />
<PackageReference Include="NuExt.Minimal.Mvvm.Wpf" />
paket add NuExt.Minimal.Mvvm.Wpf --version 0.7.3
#r "nuget: NuExt.Minimal.Mvvm.Wpf, 0.7.3"
#:package NuExt.Minimal.Mvvm.Wpf@0.7.3
#addin nuget:?package=NuExt.Minimal.Mvvm.Wpf&version=0.7.3
#tool nuget:?package=NuExt.Minimal.Mvvm.Wpf&version=0.7.3
NuExt.Minimal.Mvvm.Wpf
NuExt.Minimal.Mvvm.Wpf is a WPF add‑on for the lightweight MVVM core (NuExt.Minimal.Mvvm). It delivers deterministic async UX, predictable window and document services, parent–child view‑model patterns, and control/window‑oriented APIs—with minimal ceremony and zero heavy dependencies.
Highlights
Parent–child and control/window‑oriented VMs
ControlViewModel/WindowViewModelmodel the UI the way WPF actually runs it: parent–child relations, deterministic event‑to‑command bindings via attached behaviors, and dispatcher‑safe operations viaIDispatcherService(each UI thread owns its own dispatcher).Explicit view composition
Predictable view resolution with overridable conventions and a safe fallback view. Use templates when you have them, or a customizableViewLocatorwhen you don’t have one. See View location below for details.Async‑first UX
Dialogs and documents are orchestrated with proper async lifecycle: view creation, VM initialization, cancellation, and clean completion—without UI deadlocks.IAsyncDialogServiceshows modal dialogs with typed commands/results and optional validation.IAsyncDocumentManagerServicemanages the creation/activation/closure of documents that live as windows or tabs.Deterministic windows and documents
Restore/save window position/size/state (WindowPlacementService). Manage documents as windows (WindowedDocumentService) or as tabs (TabbedDocumentService) using a unifiedIAsyncDocumentcontract (ID, title,Show/Hide/CloseAsync, “dispose VM on close”, optional “hide instead of close”).Multi‑threaded WPF ready
Works in multi‑UI‑thread apps (each window on its own dispatcher).DispatcherServiceis injected per thread; window‑oriented services are dispatcher‑aware by design.Minimal deps, performance‑oriented
No heavy external frameworks. Hot paths avoid needless allocations, lifecycle is explicit, and services/events are carefully cleaned up.Compatibility:
WPF on .NET 8/9/10 and .NET Framework 4.6.2+. Works with any MVVM stack and pairs naturally withNuExt.Minimal.Mvvm.
Key concepts
Control/Window‑oriented VMs + DispatcherService — VMs expose a predictable async lifecycle and run code on the owning UI thread via
IDispatcherService. This is why the same patterns also work in multi‑threaded WPF, where each window has its own dispatcher.IAsyncDocument + IAsyncDocumentManagerService — a document is a hosted view + VM with a stable contract (
Id,Title,Show/Hide/CloseAsync, optional “dispose VM on close”). The manager creates documents (CreateDocumentAsync), tracksActiveDocument, enumeratesDocuments, supports bulkCloseAllAsync, and plugs into WPF as windows (WindowedDocumentService) or tabs (TabbedDocumentService).IAsyncDialogService — shows modal dialogs with a view resolved by name/template and a view‑model you provide; returns either a
MessageBoxResultor a selectedUICommand. The service handles view creation, optional title binding, validation (viaIDataErrorInfo/INotifyDataErrorInfo), and clean teardown.
View location (predictable, overridable)
Views are resolved in a strict order by the window/document services:
ViewTemplate → ViewTemplateKey → ViewTemplateSelector → ViewLocator.
The default ViewLocator searches loaded assemblies, caches types, and produces a fallback view if nothing matches.
Register a custom view name (e.g., when you don’t follow naming conventions):
// if the default locator is the built-in ViewLocator, you can register names:
if (Minimal.Mvvm.Wpf.ViewLocator.Default is Minimal.Mvvm.Wpf.ViewLocator v)
{
v.RegisterType("MyCustomView", typeof(MyCustomView));
}
Fallback view
When no view is found (or view creation fails), a lightweight FallbackView is created with a readable error text. Override ViewLocatorBase or assign ViewLocator.Default if you need full control over lookup rules. If you need to alter caches or registrations during long‑running sessions, the built‑in locator also exposes ClearCache() and ClearRegisteredTypes().
Windowed vs ViewWindowService
When to use which:
- Use
WindowedDocumentServicewhen you manage multiple long‑lived windows as documents (ID reuse, ActiveDocument, bulk close). - Use
ViewWindowServicewhen you occasionally show a view as a window (modal/non‑modal) without keeping a document roster.
Quick Start (practical, minimal)
1) Async dialog with validation + automatic window placement
XAML (attach services to your Window via behaviors):
<Window
...
xmlns:nx="http://schemas.nuext.minimal/xaml">
<nx:Interaction.Behaviors>
<nx:WindowService/>
<nx:InputDialogService
x:Name="Dialogs"
MessageBoxButtonLocalizer="{StaticResource MessageBoxButtonLocalizer}"
ValidatesOnDataErrors="True"
ValidatesOnNotifyDataErrors="True"/>
<nx:WindowPlacementService
FileName="MainWindow"
DirectoryName="{Binding EnvironmentService.SettingsDirectory, FallbackValue={x:Null}}"/>
</nx:Interaction.Behaviors>
</Window>
ViewModel (show a dialog with a view and a VM):
private IAsyncDialogService Dialogs => GetService<IAsyncDialogService>("Dialogs");
public async Task EditAsync(MyModel myModel, CancellationToken ct)
{
await using var vm = new EditViewModel();
var result = await Dialogs.ShowDialogAsync(
MessageBoxButton.OKCancel,
title: "Edit",
documentType: "EditView",
viewModel: vm,
parentViewModel: this,
parameter: myModel,
cancellationToken: ct);
if (result != MessageBoxResult.OK) return;
// proceed with the edited model
}
WindowPlacementService is fully automatic once attached: it restores on load and saves on close—no extra code needed.
2) Documents as windows (ID‑based reuse + per‑window behaviors)
XAML (window manager + per‑window template behaviors):
<nx:Interaction.Behaviors>
<nx:WindowedDocumentService x:Name="Windows"
ActiveDocument="{Binding ActiveWindow}"
FallbackViewType="{x:Type views:ErrorView}">
<nx:WindowedDocumentService.WindowStyle>
<Style TargetType="{x:Type Window}">
<Setter Property="nx:Interaction.BehaviorsTemplate">
<Setter.Value>
<DataTemplate>
<ItemsControl>
<nx:WindowService Name="CurrentWindowService"/>
<nx:EventToCommand EventName="ContentRendered"
Command="{Binding ContentRenderedCommand}"/>
</ItemsControl>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</nx:WindowedDocumentService.WindowStyle>
</nx:WindowedDocumentService>
</nx:Interaction.Behaviors>
ViewModel (find by ID or create; dispose VM on close):
public IAsyncDocumentManagerService WindowManager => GetService<IAsyncDocumentManagerService>("Windows");
public async Task OpenInWindowAsync(MyModel myModel, CancellationToken ct)
{
var doc = await WindowManager.FindDocumentByIdOrCreateAsync(
id: myModel.Id,
createDocumentCallback: async mgr =>
{
var vm = new MyModelViewModel();
try
{
var d = await mgr.CreateDocumentAsync(
documentType: "MyModelView",
viewModel: vm,
parentViewModel: this,
parameter: myModel,
cancellationToken: ct);
d.DisposeOnClose = true;
return d;
}
catch
{
await vm.DisposeAsync();
throw;
}
});
doc.Show();
}
3) Parent–child helper (sticky parent binding)
Use ViewModelExtensions.ParentViewModel to set a parent VM on child view models directly in XAML; enable StickyParentBinding="True" to keep it in sync on every DataContext change.
<ContentPresenter
xmlns:nx="http://schemas.nuext.minimal/xaml"
nx:ViewModelExtensions.ParentViewModel="{Binding}"
nx:ViewModelExtensions.StickyParentBinding="True"
Content="{Binding ChildVm}"/>
4) Multi‑threaded WPF (per‑thread dispatcher, window‑oriented services)
Each UI thread has its own DispatcherService instance injected via behaviors; window‑oriented services (ViewWindowService / WindowedDocumentService) are dispatcher‑aware and safe to call on the owning thread.
See the runnable samples:
- Multi‑threaded app: WpfMultiThreadedApp
- Basic app (services/commands/VMs): WpfAppSample
Installation
Via NuGet:
dotnet add package NuExt.Minimal.Mvvm.Wpf
Or via Visual Studio:
- Go to
Tools -> NuGet Package Manager -> Manage NuGet Packages for Solution.... - Search for
NuExt.Minimal.Mvvm.Wpf. - Click "Install".
Nice to have: NuExt.Minimal.Mvvm.SourceGenerator to remove boilerplate in view‑models. Also see NuExt.Minimal.Mvvm.MahApps.Metro - a NuGet package that provides extensions for integrating with MahApps.Metro.
- NuExt.Minimal.Mvvm
- NuExt.Minimal.Mvvm.SourceGenerator
- NuExt.Minimal.Behaviors.Wpf
- NuExt.Minimal.Mvvm.MahApps.Metro
- NuExt.System
- NuExt.System.Data
- NuExt.System.Data.SQLite
Contributing
Issues and PRs are welcome. Keep changes minimal and performance-conscious.
Acknowledgements
The DevExpress MVVM Framework has been a long‑time source of inspiration. NuExt.Minimal.Mvvm.Wpf distills similar ideas into a lightweight, async‑first, and explicit composition model tailored for contemporary WPF apps.
License
MIT. See LICENSE.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0-windows7.0 is compatible. net9.0-windows was computed. net9.0-windows7.0 is compatible. net10.0-windows was computed. net10.0-windows7.0 is compatible. |
| .NET Framework | net462 is compatible. net463 was computed. net47 was computed. net471 is compatible. net472 was computed. net48 was computed. net481 was computed. |
-
.NETFramework 4.6.2
- NuExt.Minimal.Behaviors.Wpf (>= 0.7.3)
- NuExt.Minimal.Mvvm (>= 0.7.3)
- NuExt.System (>= 0.7.3)
-
.NETFramework 4.7.1
- NuExt.Minimal.Behaviors.Wpf (>= 0.7.3)
- NuExt.Minimal.Mvvm (>= 0.7.3)
- NuExt.System (>= 0.7.3)
-
net10.0-windows7.0
- NuExt.Minimal.Behaviors.Wpf (>= 0.7.3)
- NuExt.Minimal.Mvvm (>= 0.7.3)
- NuExt.System (>= 0.7.3)
-
net8.0-windows7.0
- NuExt.Minimal.Behaviors.Wpf (>= 0.7.3)
- NuExt.Minimal.Mvvm (>= 0.7.3)
- NuExt.System (>= 0.7.3)
-
net9.0-windows7.0
- NuExt.Minimal.Behaviors.Wpf (>= 0.7.3)
- NuExt.Minimal.Mvvm (>= 0.7.3)
- NuExt.System (>= 0.7.3)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on NuExt.Minimal.Mvvm.Wpf:
| Package | Downloads |
|---|---|
|
NuExt.Minimal.Mvvm.MahApps.Metro
Extensions for the MahApps.Metro toolkit using the Minimal MVVM Framework for streamlined Metro-style WPF app development. Commonly Used Types: Minimal.Mvvm.Wpf.DialogCoordinatorService Minimal.Mvvm.Wpf.MetroDialogService Minimal.Mvvm.Wpf.MetroTabbedDocumentService MahApps.Metro.Controls.Dialogs.MetroDialog |
GitHub repositories
This package is not used by any popular GitHub repositories.