OutWit.Common.MVVM.Blazor 2.0.2

dotnet add package OutWit.Common.MVVM.Blazor --version 2.0.2
                    
NuGet\Install-Package OutWit.Common.MVVM.Blazor -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.Blazor" 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.Blazor" Version="2.0.2" />
                    
Directory.Packages.props
<PackageReference Include="OutWit.Common.MVVM.Blazor" />
                    
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.Blazor --version 2.0.2
                    
#r "nuget: OutWit.Common.MVVM.Blazor, 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.Blazor@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.Blazor&version=2.0.2
                    
Install as a Cake Addin
#tool nuget:?package=OutWit.Common.MVVM.Blazor&version=2.0.2
                    
Install as a Cake Tool

OutWit.Common.MVVM.Blazor

Blazor-specific MVVM components and utilities for building Blazor applications with the MVVM pattern.

Features

  • ViewModelBase: Base class combining ComponentBase with INotifyPropertyChanged
  • ViewModelBaseAsync: Extended base with async lifecycle support and error handling
  • BlazorDispatcher: IDispatcher implementation for UI thread invocation
  • SafeObservableCollection: Collection with automatic StateHasChanged callbacks
  • Component Extensions: Helper methods for Blazor components

Installation

dotnet add package OutWit.Common.MVVM.Blazor

This automatically includes:

  • OutWit.Common.MVVM (base cross-platform package)
  • OutWit.Common.Logging

Quick Start

ViewModelBase

The simplest way to create a Blazor component with MVVM support:

@inherits ViewModelBase

<h1>Counter: @Count</h1>
<button @onclick="IncrementCount" disabled="@Busy">
    @(Busy ? "Loading..." : "Increment")
</button>

@code {
    private int _count;
    
    public int Count
    {
        get => _count;
        set => SetProperty(ref _count, value);
    }

    private async Task IncrementCount()
    {
        await RunAsync(async () =>
        {
            await Task.Delay(500); // Simulate work
            Count++;
        });
    }
}

ViewModelBase Features

public class MyViewModel : ViewModelBase
{
    private string _name = "";
    private int _count;

    // Property with automatic change notification
    public string Name
    {
        get => _name;
        set => SetProperty(ref _name, value);
    }

    public int Count
    {
        get => _count;
        set => SetProperty(ref _count, value);
    }

    // Run async operation with automatic Busy state management
    public async Task LoadDataAsync()
    {
        await RunAsync(async () =>
        {
            var data = await FetchDataAsync();
            Name = data.Name;
        });
        // Busy is automatically set to true/false
        // StateHasChanged is called automatically after completion
    }

    // Safe execution with error handling
    public void SafeOperation()
    {
        // Returns default on exception
        var result = Check(() => int.Parse("invalid"), defaultValue: 0);
        
        // Returns false on exception
        var success = Check(() => RiskyOperation());
        
        // Swallows exception
        Check(() => MayThrow());
    }

    // React to property changes
    protected override void OnPropertyChanged(string? propertyName)
    {
        if (propertyName == nameof(Name))
        {
            // Handle name change
        }
    }
}

ViewModelBaseAsync

Extended base class with async initialization and error handling:

@inherits ViewModelBaseAsync

@if (HasError)
{
    <div class="alert alert-danger">@Error</div>
}
else if (Busy)
{
    <div>Loading...</div>
}
else
{
    <div>@Data</div>
}

@code {
    public string? Data { get; private set; }

    // Called during OnInitializedAsync - errors are caught automatically
    protected override async Task InitializeAsync()
    {
        Data = await LoadDataAsync();
    }

    // Optional: Handle initialization errors
    protected override void OnInitializationError(Exception ex)
    {
        // Log error, show notification, etc.
    }
}

SafeObservableCollection

Collection that automatically notifies UI when modified:

@inherits ViewModelBase

<ul>
    @foreach (var item in Items)
    {
        <li>@item</li>
    }
</ul>

@code {
    // Collection with automatic StateHasChanged callback
    public SafeObservableCollection<string> Items { get; private set; } = null!;

    protected override void OnInitialized()
    {
        // Pass StateHasChanged action to automatically refresh UI on changes
        Items = new SafeObservableCollection<string>(() => StateHasChanged());
        Items.Add("Item 1");
        Items.Add("Item 2");
    }

    private void AddItem(string item)
    {
        Items.Add(item); // UI automatically updates
    }
}

Component Extensions

using OutWit.Common.MVVM.Blazor.Utils;

// Force UI update
component.ForceUpdate();

// Run with busy state
await component.RunWithBusyAsync(
    () => _busy,
    v => _busy = v,
    async () => await DoWorkAsync()
);

ViewModelBase API

Member Type Description
Busy bool Indicates if async operation is running
PropertyChanged event Fired when property value changes
SetProperty<T> method Sets property and raises PropertyChanged
RaisePropertyChanged method Manually raises PropertyChanged
RunAsync method Runs async operation with Busy management
Check<T> method Executes with error handling
InvokeOnUIAsync method Invokes on UI thread

ViewModelBaseAsync API

Includes all ViewModelBase members plus:

Member Type Description
Error string? Error message from initialization
HasError bool Indicates if there's an error
InitializeAsync method Override for async initialization
OnInitializationError method Called when initialization fails
DisposeAsync method Async dispose support

Design Considerations

Why No Source Generator?

Unlike WPF and Avalonia, Blazor doesn't have a DependencyProperty or StyledProperty equivalent. Blazor uses:

  • [Parameter] attribute for component parameters (built-in)
  • [CascadingParameter] for cascading values (built-in)
  • Standard C# properties with INotifyPropertyChanged

The existing Blazor infrastructure handles these patterns well, so a source generator isn't necessary.

Differences from WPF/Avalonia

Feature WPF/Avalonia Blazor
Property System DependencyProperty/StyledProperty Standard C# + INotifyPropertyChanged
UI Thread Dispatcher SynchronizationContext + InvokeAsync
Visual Tree Yes Render Tree (different model)
Data Binding XAML Binding Razor @bind
  • OutWit.Common.MVVM - Cross-platform base classes
  • OutWit.Common.MVVM.WPF - WPF-specific implementation
  • OutWit.Common.MVVM.Avalonia - Avalonia-specific implementation

License

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

Attribution (optional)

If you use OutWit.Common.MVVM.Blazor in a product, a mention is appreciated (but not required), for example: "Powered by OutWit.Common.MVVM.Blazor (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.Blazor");
  • use the name to indicate compatibility (e.g., "OutWit.Common.MVVM.Blazor-compatible").

You may not:

  • use "OutWit.Common.MVVM.Blazor" 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.Blazor logo to promote forks or derived products without permission.
Product Compatible and additional computed target framework versions.
.NET 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (2)

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

Package Downloads
OutWit.Web.Framework

WitDocs Framework: Blazor WebAssembly framework for creating static websites with markdown content, SEO optimization, skeleton loading, and automatic content generation. Part of https://witdocs.io

OutWit.Common.Blazor.Logging

Blazor WebAssembly log viewer components built on MudBlazor. Provides a toolbar, filter tree, table, and detail panel for querying and displaying NewRelic logs.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.0.2 180 1/25/2026
2.0.1 102 1/8/2026
2.0.0 294 1/2/2026