Skip to content

[Feature] Basic MVVM primitives (.NET Standard) #3230

@Sergio0694

Description

@Sergio0694

Describe the problem this feature would solve

Follow up from the conversation with @michael-hawker on the UWP Community Discord server.

With the MvvmLight library not being supported anymore, and other existing libraries being much bigger in scope that what is often needed for simple apps, I was wondering whether we should add some basics MVVM primitives to the toolkit, possibly in a new Microsoft.Toolkit.Mvvm package so that users not in need of those wouldn't have to reference those too. We're also using this occasion to integrate with the Microsoft.Extensions.DependencyInjection package to provide dependency injection features, so that it'll be both easier for devs to interoperate between this package and existing code, as well as allowing us to offload that part of the code to an official library from Microsoft.

All this would come together in a new Microsoft.Toolkit.Mvvm package.

Preview package

The CI is now running for #3229 , so you should be able to just get the latest package from the CI build artifacts.

Key Tenants

  • Platform and Runtime Independent - .NET Standard 2.0 🚀 (UI Framework Agnostic)
  • Simple to pick-up and use - No strict requirements on Application structure or coding-paradigms (outside of 'MVVM'ness) i.e. flexible usage
  • À la carte - Developer able to choose the components they wish to leverage
  • Reference Implementation - Lean and performant, provides compliments to interfaces and paradigms hinted at in the Base-Class Library, but without provided implementations.

Draft docs here 📖

Feature set 🧰

The idea for this package would be to have a series of common, self-contained, lightweight types:

  • Microsoft.Toolkit.Mvvm.ComponentModel
    • ObservableObject
    • ViewModelBase
  • Microsoft.Toolkit.Mvvm.DependencyInjection
    • Ioc
  • Microsoft.Toolkit.Mvvm.Input
    • RelayCommand
    • RelayCommand<T>
    • AsyncRelayCommand
    • AsyncRelayCommand<T>
    • IRelayCommand
    • IRelayCommand<in T>
    • IAsyncRelayCommand
    • IAsyncRelayCommand<in T>
  • Microsoft.Toolkit.Mvvm.Messaging
    • Messenger
    • IMessenger
  • Microsoft.Toolkit.Mvvm.Messaging.Messages
    • PropertyChangedMessage<T>
    • RequestMessage<T>
    • AsyncRequestMessage<T>
    • CollectionRequestMessage<T>
    • AsyncCollectionRequestMessage<T>
    • ValueChangedMessage<T>

These types alone are usually enough for many users building apps using the MVVM toolkit.
Having these built right into the toolkit would allow them to just reference the new package and bet all set, without having to go dig through other documentation and referencing a series of external packages just to gain access to these basic types. Furthermore, we could keep these smaller in scopes than other big libraries like autofac or Prism, which include a lot of features that are not necessarily useful for many (particularly non-enterprise) devs, while still taking a toll on performance and memory usage. This would also make the learning curve much less steep for developers.

As an example of the benefit of a more modern codebase, which is both more optimized and minimalistic, here's a benchmark showing the performance of the Messenger class from both MvvmLight and Calcium, and the one from the related PR (WCT stands for this new Mvvm package). Note that Calcium only supports a single channel mode:

image

Some summarized results for the Messenger class from #3229:

  • Single channel: ~40x faster than MvvmLight, and ~11% faster than Calcium. At the same time, it uses about 38 million times less memory than MvvmLight, specifically just 20 bytes vs. almost 700MB (!), and about 387,000x less memory than Calcium as well, specifically again just 20 bytes vs. about 7 MB.
  • Multiple channels: about 11x times faster than MvvmLight, and using almost 7 million times less memory, specifically just 416 bytes vs almost 3 GB (!).

The full benchmark code can be found here.

Describe the solution

As mentioned above, and as can be seen in the related PR #3229, this proposal is to add a new Microsoft.Toolkit.Mvvm package, integrating some features from MvvmLight, refactoring them when needed, in order to offer a self-contained alternative. The package would not need a reference to any other Microsoft.Toolkit packages, it would be lightweight and focused on ease of use, performance and memory efficiency.

Since it targets .NET Standard 2.0, this means that it can be used anywhere from UWP apps, to Uno, Xamarin, Unity, ASP.NET, etc. Literally any framework supporting the .NET Standard 2.0 feature set. There are no platform specific dependencies at all. The whole package is entirely platform, runtime, and UI stack agnostic.

Additionally, it would integrate with the existing Microsoft.Extensions.DependencyInjection package, to offer a well known and tested DI platform, with the addition of an easy to use entry point in the toolkit, especially for new users. This would also remove a lot of code from the actual Mvvm package, as there would not be the need to write and maintain yet another DI library or set of APIs.

As mentioned above, the package would target .NET Standard 2.0 to have as much reach as possible, and it wouldn't have any platform-specific dependencies.

Having a set of MVVM-enabled features built-in into the toolkit would align with the general philosophy of the toolkit to help developers getting started in common scenarios (such as with the MVVM pattern), and it would complement all the available APIs from the BCL that just lack a "reference" implementation (such as INotifyPropertyChanged or ICommand).

Furthermore, having a package like this being published by a Microsoft supported project directly would be a big selling points for users not wanting to add "3rd party" references to their projects (this point has been brought up before in the comments below as well by other users).

Describe alternatives you've considered

As mentioned above, common alternatives like autofac, Fody or Prism are much bigger in scope than what many devs typically need and introduce more overhead. MvvmLight on the other hand is also not supported anymore, other than some forks.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions