OutWit.Common.MVVM 2.0.2

dotnet add package OutWit.Common.MVVM --version 2.0.2
                    
NuGet\Install-Package OutWit.Common.MVVM -Version 2.0.2
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="OutWit.Common.MVVM" Version="2.0.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="OutWit.Common.MVVM" Version="2.0.2" />
                    
Directory.Packages.props
<PackageReference Include="OutWit.Common.MVVM" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add OutWit.Common.MVVM --version 2.0.2
                    
#r "nuget: OutWit.Common.MVVM, 2.0.2"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package OutWit.Common.MVVM@2.0.2
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=OutWit.Common.MVVM&version=2.0.2
                    
Install as a Cake Addin
#tool nuget:?package=OutWit.Common.MVVM&version=2.0.2
                    
Install as a Cake Tool

OutWit.Common.MVVM

Cross-platform MVVM library providing base components for building modern .NET applications with WPF, Avalonia, and Blazor.

Features

  • Cross-Platform ViewModelBase: Base class for view models with INotifyPropertyChanged support
  • Command Implementations:
    • RelayCommand: Simple command with manual CanExecuteChanged raising
    • DelegateCommand<T>: Generic typed command
  • Collections:
    • SortedCollection<TKey, TValue>: Sorted collection with change notifications
    • ObservableSortedCollection<TKey, TValue>: Sorted collection observing item property changes
    • SafeObservableCollection<T>: Thread-safe observable collection
  • Table Models: Data models for table views (TableView, TableViewPage, TableViewRow, etc.)
  • Abstractions: IDispatcher for cross-platform thread marshalling

Installation

dotnet add package OutWit.Common.MVVM

For platform-specific features:

# WPF
dotnet add package OutWit.Common.MVVM.WPF

# Avalonia
dotnet add package OutWit.Common.MVVM.Avalonia

# Blazor
dotnet add package OutWit.Common.MVVM.Blazor

Quick Start

ViewModelBase

public class MyViewModel : ViewModelBase<IApplicationViewModel>
{
    private string m_name = "";

    public MyViewModel(IApplicationViewModel appVm) : base(appVm)
    {
    }

    public string Name
    {
        get => m_name;
        set
        {
            m_name = value;
            OnPropertyChanged();
        }
    }
}

RelayCommand

public class MyViewModel : ViewModelBase<IApplicationViewModel>
{
    public RelayCommand SaveCommand { get; }

    public MyViewModel(IApplicationViewModel appVm) : base(appVm)
    {
        SaveCommand = new RelayCommand(
            execute: _ => Save(),
            canExecute: _ => CanSave());
    }

    private void Save() { /* Save logic */ }
    
    private bool CanSave() => !string.IsNullOrEmpty(Name);

    private void OnNameChanged()
    {
        SaveCommand.RaiseCanExecuteChanged();
    }
}

DelegateCommand<T>

public DelegateCommand<string> SearchCommand { get; }

SearchCommand = new DelegateCommand<string>(
    execute: searchText => PerformSearch(searchText),
    canExecute: searchText => !string.IsNullOrEmpty(searchText));

SortedCollection

Thread-safe sorted collection with change notifications:

var items = new SortedCollection<int, Item>(x => x.Id);

items.ItemsAdded += (s, added) => Console.WriteLine($"Added {added.Count} items");
items.ItemsRemoved += (s, removed) => Console.WriteLine($"Removed {removed.Count} items");

items.Add(new Item { Id = 1, Name = "First" });

ObservableSortedCollection

Observes property changes in collection items:

var items = new ObservableSortedCollection<int, Item>(x => x.Id);

// Listen for item property changes
items.CollectionContentChanged += (sender, e) => 
{
    var item = sender as Item;
    Console.WriteLine($"Property {e.PropertyName} changed on item {item?.Id}");
};

items.Add(new Item { Id = 1, Name = "First" });
items[1].Name = "Updated"; // Triggers CollectionContentChanged

SafeObservableCollection with IDispatcher

// Thread-safe collection that marshals notifications to UI thread
var items = new SafeObservableCollection<Item>(dispatcher);

// Safe to call from background thread
await Task.Run(() => 
{
    foreach (var item in loadedItems)
    {
        items.Add(item); // UI updates happen on correct thread
    }
});

Platform-Specific Packages

Package Platform Features
OutWit.Common.MVVM.WPF WPF DependencyProperty source generator, WPF commands, visual tree utilities
OutWit.Common.MVVM.Avalonia Avalonia StyledProperty/DirectProperty source generator, Avalonia utilities
OutWit.Common.MVVM.Blazor Blazor ViewModelBase for ComponentBase, async lifecycle support

Migration from v1.x

See the Migration Guide for detailed instructions.

Key changes:

  • Split into cross-platform base and platform-specific packages
  • New source generator-based property system
  • BindableAttribute is obsolete (use StyledPropertyAttribute)
  • SortedCollectionEx renamed to ObservableSortedCollection
  • OutWit.Common.MVVM.WPF - WPF-specific implementation
  • OutWit.Common.MVVM.Avalonia - Avalonia-specific implementation
  • OutWit.Common.MVVM.Blazor - Blazor-specific implementation

License

Licensed under the Apache License, Version 2.0. See LICENSE.

Attribution (optional)

If you use OutWit.Common.MVVM in a product, a mention is appreciated (but not required), for example: "Powered by OutWit.Common.MVVM (https://ratner.io/)".

Trademark / Project name

"OutWit" and the OutWit logo are used to identify the official project by Dmitry Ratner.

You may:

  • refer to the project name in a factual way (e.g., "built with OutWit.Common.MVVM");
  • use the name to indicate compatibility (e.g., "OutWit.Common.MVVM-compatible").

You may not:

  • use "OutWit.Common.MVVM" as the name of a fork or a derived product in a way that implies it is the official project;
  • use the OutWit.Common.MVVM logo to promote forks or derived products without permission.
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (3)

Showing the top 3 NuGet packages that depend on OutWit.Common.MVVM:

Package Downloads
OutWit.Common.MVVM.Blazor

Blazor-specific helpers and components for the MVVM pattern. Includes ViewModelBase, BlazorDispatcher, and utilities for building Blazor applications with MVVM pattern. This is part of the OutWit.Common.MVVM family of libraries.

OutWit.Common.MVVM.Avalonia

Avalonia-specific helpers and components for the MVVM pattern. Includes AvaloniaDispatcher, BindingUtils, visual tree traversal utilities, and automatic StyledProperty/DirectProperty generation via source generator and AspectInjector. This is part of the OutWit.Common.MVVM family of libraries.

OutWit.Common.MVVM.WPF

WPF-specific helpers and components for the MVVM pattern. Includes Command, BindingUtils, DataTemplateUtils, visual tree traversal utilities, and automatic DependencyProperty generation via source generator and AspectInjector. This is part of the OutWit.Common.MVVM family of libraries.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.0.2 471 1/25/2026
2.0.1 182 1/8/2026
2.0.0 421 1/2/2026
1.1.3 171 8/16/2025
1.1.1 232 6/30/2025
1.1.0 146 6/7/2025
1.0.1 213 11/24/2024
1.0.0 190 10/13/2024