MauiMicroMvvm for all of your small apps

Share this post:

For many it may come as a surprise that I put this together or even that I published it. After all normally you would hear me talk about how you should use Prism. You might ask has something changed? The answer is no, nothing has changed. I do however understand that sometimes you might want something that is minimalistic and works with Shell. While I continue to believe Shell is the exact wrong answer for any Enterprise application, there are still a whole host of small apps out there for which Shell may be a good fit. So why write yet another MVVM Framework for it?

The truth is that I've looked at what's out there, and needless to say I feel they miss the mark in some very significant ways. Some of the things I see done wrong over and over in the Xamarin/.NET MAUI space are:

  1. Not understanding a View in MVVM terms is not a Page. In fact if we're using MAUI speak it would be a VisualElement as a View could be a Page, or any MAUI View.
  2. Either not understanding that in MVVM the View and the ViewModel should be decoupled. In fact the ViewModel itself should be completely testable without the View or View types.
  3. Not having a solid grasp on Dependency Injection. While I could easily critique some of the MAUI API itself on this one, the MAUI API has made huge changes to make DI a more First Class experience, and this will only continue to be refined and improve over time. Sadly many of the community frameworks I have looked through still do not demonstrate a proper reliance on Dependency Injection and instead use anti-patterns that stem from and lead to bad architecture.
  4. Thinking you need to reinvent the wheel. For those who have been around for a while you're probably familiar with the ICommand. There are a lot of decent, and a few pretty good implementations of the ICommand including Prism's DelegateCommand, ReactiveUI's ReactiveCommand, and MVVMLight (now the Microsoft.CommunityToolkit's) RelayCommand. Unless you're really trying to provide some special functionality around the ICommand, in my opinion it doesn't belong in the MVVM Framework particularly as MAUI already has a built in Command that works great in many cases.
  5. Forcing you to adopt a specific type of base View or ViewModel class. This one should be pretty evident why it's a bad idea, what happens when I want to adopt some 3rd party library that gives me some special functionality... If I have to use the base type from the MVVM library I lose the ability to customize my app.

After looking at some of the options out there in the community I decided to put something together that people could use that solves these problems. I call it MauiMicroMvvm or MauiMicro for short. It's a micro Mvvm framework that is designed to provide only what you absolutely need and nothing that you don't. Naturally it does have a base ViewModel type that implements INotifyPropertyChanged, but it also has some lifecycle abstractions that are helpful for those that might want to use something like ReactiveUI. As you might guess, it also includes some abstractions around Navigation & showing native Dialogs that help you to keep your code testable.

Getting Started

When using MauiMicro you actually can start by deleting the Application. Unless you absolutely need to override methods in the Application you can actually have just the AppShell and your Pages to get off the ground and you can even provide the resource paths for your styles just like you would in XAML. The result is something like the following:

    var builder = MauiApp.CreateBuilder();
builder.UseMauiMicroMvvm<AppShell>("Resources/Styles/Colors.xaml", "Resources/Styles/Styles.xaml")
    .ConfigureFonts(fonts =>
    {
        fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
        fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
    });
builder.Services.MapView<MainPage, MainPageViewModel>();
return builder.Build();
  

Any view that has been mapped using the MapView extension can now be auto-wired using the attached property like:

    <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:micro="http://schemas.mauimicromvvm.com/2022/dotnet/maui"
             micro:MauiMicro.Autowire="True">
  

With the View autowired, this will automatically resolve our ViewModel and set the BindingContext for us. Next it will attach a lifecycle helper Behavior that will help us get notified when the View has appeared or disappeared, and when the App goes to Sleep or Resumes. The result in our ViewModel is something like this:

    public class MainPageViewModel : MauiMicroViewModel
{
    public MainPageViewModel(ViewModelContext context)
        : base(context)
    {
    }

    protected override void OnParametersSet()
    {
        // Provide any custom logic for initialization when Navigation Parameters are set
    }

    public override void OnFirstLoad()
    {
        // Do something the first time the View appears
    }

    public override void OnAppearing()
    {
        // Do something anytime the View Appears
    }

    public override void OnDisappearing()
    {
        // Do something anytime the View Disappears
    }

    public override void OnResume()
    {
        // Do something when the app resumes
    }

    public override void OnSleep()
    {
        // Do something when the app goes to sleep
    }
}
  

As a benefit of using the MauiMicroViewModel in addition to the MauiMicro specific interfaces, this also implements IQueryAttributable from .NET MAUI and it will automatically set the values of your properties for you. To make it even easier, when using the MauiMicroViewModel there is no need for a backing field as the MauiMicroViewModel makes use of an internal dictionary with a Get/Set that makes setting properties as easy as:

    public string Message
{
    get => Get<string>();
    set => Set(value);
}
  

Next Steps

If you're looking for a lightweight framework to build Shell apps with, and you want to be sure that you're using a framework that keeps your code testable, and keeps you on the path towards Good Architectural Design, then you'll want to use MauiMicro. While there isn't currently a template for it, as you can see from this post there isn't much you need to do to convert a standard MAUI template.

Categories: .net maui
Tags: maui mauimicro mvvm
Share this post:

Comments

Be the first to leave a comment


Leave a Comment