MvvmEssence 1.2.1

.NET Standard 2.0
dotnet add package MvvmEssence --version 1.2.1
NuGet\Install-Package MvvmEssence -Version 1.2.1
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="MvvmEssence" Version="1.2.1" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add MvvmEssence --version 1.2.1
#r "nuget: MvvmEssence, 1.2.1"
#r directive can be used in F# Interactive, C# scripting and .NET Interactive. Copy this into the interactive tool or source code of the script to reference the package.
// Install MvvmEssence as a Cake Addin
#addin nuget:?package=MvvmEssence&version=1.2.1

// Install MvvmEssence as a Cake Tool
#tool nuget:?package=MvvmEssence&version=1.2.1


This is a .NET standard 2.0 library, can be used in WPF, Xamarin Forms and MAUI projects as well.


Define your ViewModel class as:

using Brain2CPU.MvvmEssence;

public class MyViewModel : ViewModelBase

In the XAML file do the binding in the usual way. In the ViewModel instead of the traditional way to declare a property used in binding or a command:

private DateTime _dateFrom = DateTime.Today;
public DateTime DateFrom
    get => _dateFrom;
        if (_dateFrom == value)

        _dateFrom = value;

private Xamarin.Forms.Command _refreshCommand;
public Xamarin.Forms.Command RefreshCommand => 
    _refreshCommand ?? (_refreshCommand = new Command(Refresh, () => !IsBusy && DateFrom > DateTime.Now));

use the following:

public DateTime DateFrom
    get => Get(defaultVal:DateTime.Today);
    set => Set(value, RefreshCommand);

public RelayCommand RefreshCommand => Get(Refresh, () => !IsBusy && DateFrom > DateTime.Now);

with the same

private void Refresh() { ... }

ViewModelBase will take care of the storage and notifications.

The Get method used in the property definition must have specified the generic type or the default value. The Set method has an optional command list parameter, for commands that must update their CanExecute state based on the property value.

Set supports a custom comparer too:

public DateTime DateTo
    get => Get<DateTime>();   //will have the type's default value
    set => Set(value, RefreshCommand, (d1, d2) => d1.Date == d2.Date);

The Get method used in the command definition has a first parameter of type Action or Action<T> and an optional canExecute Func<bool> parameter.

For the case of an asynchronous method servicing a command, instead of a fire-and-forget approach async void Handler() you can use RelayCommandAsync with a proper async Task HandlerAsync(). Keep in mind that this is a syntactic sugar, the execution of the method won't be awaited, so handle all exceptions inside the method!

The IsBusy property setter will call RaiseCanExecuteChanged for every command.

There is a Get overload having a delegate parameter bool IsValid(object o), in this case every set will trigger a validaton, the global result is in the IsObjectValid property, a collection of the names of the invalid properties is stored in InvalidFields. If a validation againts the default values are required you must call the InitializeObject() method.

In order to help in situations where asynchronous initialization is required during the view model construction there is a virtual method InitializeAsync called from the default constructor. Important: please pay attention to the fact that StartInitialization is called before the child class constructor is even started, so the auto-initialized constructor can be used only if the child constructor is empty or whatever initialization is done in it will not affect the async initialization. Otherwise you should use the constructor with a boolean parameter and start the initialization in the child class. The end of initialization can be observed using the IsInitialized property or/and by subscribing to the OnInitialized event.


This class is not strictly required for the MVVM pattern but it is very useful in many situations. It extends ObservableCollection restricting it to observable items and allows temporary notification suppression and range operations (AddRange, RemoveRange). The main addition though is that the OnCollectionChanged event is triggered not only when the collection is changed (add/remove items) but also when an observable property of any contained item is modified.


Another addition to the package, used mainly to help on component registration in MAUI DI engine.

var discover = new DiscoverComponents(typeof(MauiProgram).Assembly, 
            "MyNamespace.Services", "MyNamespace.Views", "MyNamespace.ViewModels");
        discover.RegisterItems(s => builder.Services.AddSingleton(s), 
            t => builder.Services.AddTransient(t),
            "ViewModel", "Page", "Service");

You can use the registration based on naming conventions or explicitly mark classes with RegisterAsTransientAttribute or RegisterAsSingletonAttribute.

Product Versions
.NET net5.0 net5.0-windows net6.0 net6.0-android net6.0-ios net6.0-maccatalyst net6.0-macos net6.0-tvos net6.0-windows net7.0 net7.0-android net7.0-ios net7.0-maccatalyst net7.0-macos net7.0-tvos net7.0-windows
.NET Core netcoreapp2.0 netcoreapp2.1 netcoreapp2.2 netcoreapp3.0 netcoreapp3.1
.NET Standard netstandard2.0 netstandard2.1
.NET Framework net461 net462 net463 net47 net471 net472 net48
MonoAndroid monoandroid
MonoMac monomac
MonoTouch monotouch
Tizen tizen40 tizen60
Xamarin.iOS xamarinios
Xamarin.Mac xamarinmac
Xamarin.TVOS xamarintvos
Xamarin.WatchOS xamarinwatchos
Compatible target framework(s)
Additional computed target framework(s)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.2.1 127 10/17/2022
1.2.0 161 5/26/2022
1.1.0 216 9/7/2021
1.0.2 295 1/17/2021
1.0.1 298 10/28/2020
1.0.0 358 10/18/2020