- NuGet
- Xamarin
- Xamarin.Forms
- dotnet
I created this tool to avoid writing boilerplate code for my ViewModels. This tool is built on top of the Rosyln .NET compiler.
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:
MvvmCodeGenerator now support these MVVM Frameworks:
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:
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.
It’s time to define your ViewModels. For this tutorial let’s imagine we have two cases:
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.
Each ViewModel
tag has 2 properties :
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
.
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:
property
property
property
You have different options to specify the Type of your property
Here you have the list of base types you can use:
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" />
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.
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>
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:
Command
tagAsyncCommand
tagEach Command
tag has different properties:
command
command
command
must have a can execute method or notcommand
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!
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:
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.
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!