MvvmEssence 1.4.3

dotnet add package MvvmEssence --version 1.4.3
NuGet\Install-Package MvvmEssence -Version 1.4.3
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.4.3" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add MvvmEssence --version 1.4.3
#r "nuget: MvvmEssence, 1.4.3"
#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.
// Install MvvmEssence as a Cake Addin
#addin nuget:?package=MvvmEssence&version=1.4.3

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


This is a .NET standard 2.0 library, can be used in WPF, Xamarin Forms and MAUI projects as well. To help the adoption of this library a sample MAUI application was added, the few existing unit tests could also help.


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 component registration in the MAUI DI engine (check the sample app).

var discover = new DiscoverComponents(typeof(MauiProgram).Assembly,
    type =>
        if (type.Namespace.Equals("Sample.Views") && type.Name.EndsWith("Page"))
            return ClassRegistrationOption.AsTransient;
        if (type.Namespace.Equals("Services"))
            return ClassRegistrationOption.AsSingleton;

        return ClassRegistrationOption.Skip;

discover.RegisterItems(sd => builder.Services.AddSingleton(sd),
    td => builder.Services.AddTransient(td),
    (sc, si) => builder.Services.AddSingleton(si, sc),
    (tc, ti) => builder.Services.AddTransient(ti, tc));

You can use the registration based on naming conventions, a selector method or explicitly marked classes with RegisterAsTransientAttribute or RegisterAsSingletonAttribute.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  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 was computed.  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 was computed.  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. 
.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.
  • .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.4.3 203 1/12/2024
1.4.2 169 12/18/2023
1.4.1 101 12/13/2023
1.4.0 117 12/6/2023
1.3.0 140 7/26/2023
1.2.1 386 10/17/2022
1.2.0 389 5/26/2022
1.1.0 320 9/7/2021
1.0.2 385 1/17/2021
1.0.1 398 10/28/2020
1.0.0 451 10/18/2020