Photo by pxhere.com

A complete overview of MvvmCodeGenerator

Save time writing your ViewModels!

Posted by Damien Aicheh on 07/31/2019 · 20 mins

MVVM code generator tool for .NET

I created this tool to avoid writing boilerplate code for my ViewModels. This tool is built on top of the Rosyln .NET compiler.

MvvmCodeGenerator

Why using this NuGet?

When you develop your project you always define a lot of properties and commands in your ViewModels. This result in dozens and tens lines that do not allow a quick reading of your file.

The idea of this NuGet is simple, you just define your commands and properties with a single line in a specific XML file, you rebuild your project and you are good to go!

This NuGet has different advantages:

  • Avoid writing boilerplate code
  • Your properties and commands are declared using the same conventions
  • Reduce the amount of code in your ViewModels
  • The ViewModels only contains the more important code
  • Migrate from one MVVM Framework to another easily
  • It support different MVVM Frameworks

MvvmCodeGenerator now support these MVVM Frameworks:

Setup

First of all, install the NuGet package to your .NetStandard project for example. Then create a new file called MvvmCodeGenMapper.xml at the root of your library project. This file will contain the definition of your ViewModels.

Now we need to choose which MVVM Framework we need to generate our ViewModels. As I said previously, MvvmCodeGenerator support these options:

  • mvvmlightlibs
  • mvvmcross
  • mvvmicro
  • freshmvvm
  • prismcore

When your choice is done let’s tell it to the generator inside the MvvmCodeGenMapper.xml file like this:

<?xml version="1.0" encoding="UTF-8" ?>
<Resources>
    <Generator Value="mvvmlightlibs" />
</Resources>    

For this tutorial I choose MvvmLightLibs. Don’t forget to install the MVVM Framework NuGet you choose into your project.

Define your ViewModels

Create the ViewModels folders

It’s time to define your ViewModels. For this tutorial let’s imagine we have two cases:

  • We need a folder with the list of our ViewModels associated to our Views
  • We need a second folder to define ItemViewModels that we need for the items in a ListView.

So to create this tree inside the Resources tags let’s do this:

<?xml version="1.0" encoding="UTF-8" ?>
<Resources>
    <Generator Value="mvvmlightlibs" />
    <ViewModels Namespace="Xamarin.Sample" DestinationFolder="ViewModel">
    </ViewModels>

    <ViewModels Namespace="Xamarin.Sample.Items" DestinationFolder="ViewModel/Items">
    </ViewModels>
</Resources>    

As you can see above, you define the namespace associated to your ViewModels and the destination folder. You have to know that MvvmCodeGenerator will create all the destination folders if they do not exist.

Create the ViewModels

Each ViewModel tag has 2 properties :

  • Key : The ViewModel name prefix
  • Base : The ViewModel name prefix of the parent class

In a lot of project we have a Root ViewModel which is a class that groups all the repetitive properties we need in each ViewModel. A basic property is the IsLoading. So to avoid to declare this property for each ViewModel you can just declare it one time in a RootViewModel and all the other ViewModels will inherit from it.

Let’s see how in our XML file:

<?xml version="1.0" encoding="UTF-8" ?>
<Resources>
    <Generator Value="mvvmlightlibs" />
    <ViewModels Namespace="Xamarin.Sample" DestinationFolder="ViewModel">
        <ViewModel Key="Root">
        </ViewModel>
        
        <ViewModel Key="Home" Base="Root">
          
        </ViewModel>
    </ViewModels>

    <ViewModels Namespace="Xamarin.Sample.Items" DestinationFolder="ViewModel/Items">
        <ItemViewModel Key="Switch">
        </ItemViewModel>
    </ViewModels>
</Resources>    

Our HomeViewModel now inherit from the RootViewModel.

Define properties

Properties

You can specify the Properties for each ViewModels:

For the Properties you have the ability to define it using the Property tag that have these values:

  • Name : The name of the property
  • Description : The comment associated to the property
  • Type : The type of the property

You have different options to specify the Type of your property

Here you have the list of base types you can use:

  • string
  • int
  • long
  • bool
  • float
  • object
  • double
  • DateTime
  • DateTimeOffset
  • TimeSpan

If we go back to our example to define an IsLoading property to our RootViewModel we just need to write:

<Property Name="IsLoading" Type="bool" Description="Gets or sets the is loading property" />

Custom types

If the type you need is not in the list of types I previously described don’t worry, you can just specify it using the complete namespace, for example:

<Property Name="House" Type="Xamarin.Sample.Models.House" Description="Gets or sets the house." />

Here I define a property using a House model that I created in my project.

Properties list

You can also declare a list of elements by using the list keyword before your type like this:

<Property Name="names" Type="list string" Description="Gets or sets all names." />
<Property Name="AllHouses" Type="list Xamarin.Sample.Models.House" Description="Gets or sets all houses." />

This will generate a IList of the type of your needs.

To summarize here you have a more complete example:

<?xml version="1.0" encoding="UTF-8" ?>
<Resources>
    <Generator Value="mvvmlightlibs" />
    <ViewModels Namespace="Xamarin.Sample" DestinationFolder="ViewModel">
        <ViewModel Key="Root">
            <Property Name="IsLoading" Type="bool" Description="Gets or sets the is loading property" />
        </ViewModel>
        
        <ViewModel Key="Home" Base="Root">
          <Property Name="Title" Type="string" Description="Gets or sets the title." />
          <Property Name="Number" Type="int" Description="Gets or sets the total number." />
          <Property Name="Degrees" Type="float" Description="Gets or sets the degrees." />
          <Property Name="MyTimeOffset" Type="DateTimeOffset" Description="Gets or sets the date and hour offset." />
          <Property Name="MyTimeSpan" Type="TimeSpan" Description="Gets or sets the time span." />
          <Property Name="Messages" Type="list string" Description="Gets or sets all messages." />
          <Property Name="MyHouse" Type="Xamarin.Sample.Models.House" Description="Gets or sets my houses." />
          <Property Name="AllHouses" Type="list Xamarin.Sample.Models.House" Description="Gets or sets all houses." />
        </ViewModel>
    </ViewModels>

    <ViewModels Namespace="Xamarin.Sample.Items" DestinationFolder="ViewModel/Items">
        <ItemViewModel Key="Switch">
          <Property Name="UnKnown" Type="object" Description="Gets or sets the unknown object." />
          <Property Name="MyDate" Type="DateTime" Description="Gets or sets the date and hour." />
        </ItemViewModel>
    </ViewModels>
</Resources>

Define commands

In your ViewModels you always need to specify some commands, so let’s do it with MvvmCodeGenerator!

Using MvvmCodeGenerator, you have the ability to define:

  • A synchronous command using the Command tag
  • An asynchronous command using the AsyncCommand tag

Each Command tag has different properties:

  • Name : The name of the command
  • Parameter : The parameter type of the command
  • CanExecute : A boolean to know if the command must have a can execute method or not
  • Description : The comment associated to the command

Here a Command example:

<Command Name="Buy"  Parameter="bool" CanExecute="true" Description="Gets or sets the command to buy a boat" />

And here an AsyncCommand example:

<AsyncCommand Name="Consultation" Parameter="int" CanExecute="true" Description="Gets or sets the command for the consultation" />

Easy to define isn’t it?

Because MvvmLightLibs and FreshMvvm async commands does not have an IsRunning property, MvvmCodeGenerator automatically generates it for you. MvvmCross and Mvvmicro already have this kind of mechanism.

Now if we go back to a complete example we can have something like this:

<?xml version="1.0" encoding="UTF-8" ?>
<Resources>
    <Generator Value="mvvmlightlibs" />
    <ViewModels Namespace="Xamarin.Sample" DestinationFolder="ViewModel">
        <ViewModel Key="Root">
            <Property Name="IsLoading" Type="bool" Description="Gets or sets the is loading property" />
            <AsyncCommand Name="InitData" Description="Gets or sets the command to init the data" />
        </ViewModel>
        
        <ViewModel Key="Home" Base="Root">
          <Property Name="Title" Type="string" Description="Gets or sets the title." />
          <Property Name="Number" Type="int" Description="Gets or sets the total number." />
          <Property Name="Degrees" Type="float" Description="Gets or sets the degrees." />
          <Property Name="MyTimeOffset" Type="DateTimeOffset" Description="Gets or sets the date and hour offset." />
          <Property Name="MyTimeSpan" Type="TimeSpan" Description="Gets or sets the time span." />
          <Property Name="Messages" Type="list string" Description="Gets or sets all messages." />
          <Property Name="MyHouse" Type="Xamarin.Sample.Models.House" Description="Gets or sets my houses." />
          <Property Name="AllHouses" Type="list Xamarin.Sample.Models.House" Description="Gets or sets all houses." />
          <Command Name="JobActivation" Description="Gets or sets the command to manager job actions such as day (de)activation and breaks" />
          <Command Name="ConsultControlFiles" Parameter="int" Description="Gets or sets the command to consult control files" />
          <Command Name="Files" Parameter="bool" CanExecute="true" Description="Gets or sets the files"/>
          <AsyncCommand Name="ConsultFiles" Description="Gets or sets the command to consult control files" />
          <AsyncCommand Name="Consult" Parameter="string" Description="Gets or sets the command to consult control files" />
          <AsyncCommand Name="Consultation" Parameter="string" CanExecute="true" Description="Gets or sets the command for the consultation" />
        </ViewModel>
    </ViewModels>

    <ViewModels Namespace="Xamarin.Sample.Items" DestinationFolder="ViewModel/Items">
        <ItemViewModel Key="Switch">
          <Property Name="UnKnown" Type="object" Description="Gets or sets the unknown object." />
          <Property Name="MyDate" Type="DateTime" Description="Gets or sets the date and hour." />
          <AsyncCommand Name="Toggle" Description="Gets or sets the toggle command" />
        </ItemViewModel>
    </ViewModels>
</Resources>

This XML will generate 3 files for each ViewModel you define, here the result for the SwitchItemViewModel:

The SwitchItemViewModel.cs:

namespace Xamarin.Sample.Items
{
    using System;
    using System.Collections.Generic;
    using System.Threading;
    using System.Threading.Tasks;
    using GalaSoft.MvvmLight.Command;

    public partial class SwitchItemViewModel
    {
    }
}

The SwitchItemViewModel.interface.g.cs:

//------------------------------------------------------------------------------ 
// <auto-generated> 
// This code was generated by MvvmCodeGenerator.
// Runtime Version:4.0.30319.42000
// 
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated> 
//------------------------------------------------------------------------------
namespace Xamarin.Sample.Items
{
    using System;
    using System.Collections.Generic;
    using System.Threading;
    using System.Threading.Tasks;
    using GalaSoft.MvvmLight.Command;

    public interface ISwitchItemViewModel : System.ComponentModel.INotifyPropertyChanged
    {
        System.Object UnKnown
        {
            get;
        }

        System.DateTime MyDate
        {
            get;
        }

        System.Boolean IsToggleCommandRunning
        {
            get;
        }

        System.Windows.Input.ICommand ToggleCommand
        {
            get;
        }
    }
}

The SwitchItemViewModel.part.g.cs:

//------------------------------------------------------------------------------ 
// <auto-generated> 
// This code was generated by MvvmCodeGenerator.
// Runtime Version:4.0.30319.42000
// 
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated> 
//------------------------------------------------------------------------------
namespace Xamarin.Sample.Items
{
    using System;
    using System.Collections.Generic;
    using System.Threading;
    using System.Threading.Tasks;
    using GalaSoft.MvvmLight.Command;

    public partial class SwitchItemViewModel : GalaSoft.MvvmLight.ViewModelBase, Xamarin.Sample.Items.ISwitchItemViewModel
    {
        private System.Object unKnown;
        private System.DateTime myDate;
        private System.Boolean isToggleCommandRunning;
        private GalaSoft.MvvmLight.Command.RelayCommand toggleCommand;
        /// <summary>
        // Gets or sets the unknown object.
        /// </summary>
        public System.Object UnKnown
        {
            get => this.unKnown;
            set => this.Set(ref this.unKnown, value);
        }

        /// <summary>
        // Gets or sets the date and hour.
        /// </summary>
        public System.DateTime MyDate
        {
            get => this.myDate;
            set => this.Set(ref this.myDate, value);
        }

        /// <summary>
        // Gets or sets the value to know if the associated async command is running.
        /// </summary>
        public System.Boolean IsToggleCommandRunning
        {
            get => this.isToggleCommandRunning;
            set => this.Set(ref this.isToggleCommandRunning, value);
        }

        /// <summary>
        // Gets or sets the toggle command
        /// </summary>
        public System.Windows.Input.ICommand ToggleCommand
        {
            get => this.toggleCommand ?? (this.toggleCommand = new GalaSoft.MvvmLight.Command.RelayCommand(async () =>
            {
                try
                {
                    this.IsToggleCommandRunning = true;
                    await ExecuteToggleCommandAsync();
                }
                catch (System.Exception ex)
                {
                    OnExecuteToggleCommandAsyncError(ex);
                }
                finally
                {
                    this.IsToggleCommandRunning = false;
                }
            }

            )); // You must implement the following method(s): ExecuteToggleCommandAsync and OnExecuteToggleCommandAsyncError
        }
    }
}

Now you just have to implements your commands inside the SwitchItemViewModel.cs file and that’s it!

Visual Studio display

When you rebuild your project you should see the ViewModels, folders and a MvvmCodeGenMapper.g.targets file generated. This last one allow Visual Studio to have your files grouped correctly.

If everything is working correctly you should see something like this:

Visual Studio File Viewer

If your files are not grouped correctly like above, please check if the MvvmCodeGenMapper.g.targets file was imported correctly in your .csproj associated to your project. If it’s not the case you can do it manually by adding this line:

<Import Project="MvvmCodeGenMapper.g.targets" />

Reload your project and you will be good to go.

Final touch

You will find a sample in the MvvmCodeGenerator Github repository to try it by your self.

Happy coding !

You liked this tutorial ? Leave a star in the associated Github repository!

Do not hesitate to follow me on to not miss my next tutorial!