The main problem of MVVM pattern used in Xamarin is the boilerplate code, starting from the implementation of INotifyPropertyChanged to the Command ChangeCanExecute method calling.
While a lot of MVVM Frameworks like Prism, MvvmLight, attempted to tackle this issue, none of them succeed.
In this article, I will show you how we will use the metaprogramming to get rid of the boilerplates and how to make our code fully declarative.
Hello World Using Xamarin and Meta Programming
- Create a new Xamarin application “
Hello Meta Programming
”. - Install the meta programming nuget package and postsharp package in the .NET standard project:
- Create the
ViewModel
:
public class MainPageViewModel
{
[DefaultValue("")]
public string Name { get; set; }
public string WelcomeMsg => $"Hello {Name}";
public ICommand Command { get; }
public MainPageViewModel()
{
Command = new Command(() => {Name="Test" }, () => Name.Length > 3);
}
}
- Create the
ViewModel
Configuration Class:
[Serializable]
public class MainPageViewModelConfiguration : ConfigurationProvider<MainPageViewModel>
{
public MainPageViewModelConfiguration()
{
this.NotifyPropertyChange(model =>model.Name );
this.NotifyPropertyChange
(model=>model.WelcomeMsg).DependOn(model =>model.Name );
this.NotifyPropertyChange
(model => model.Command).DependOn(model => model.Name);
}
}
This class must be Serializable
as it will be used to tell the compiler how to wave your view model class.
this.NotifyPropertyChange(model =>model.Name );
Tell the compiler to add PropertyChanged event firing in the property “Name
” in the view model.
this.NotifyPropertyChange(model=>model.WelcomeMsg).DependOn(model =>model.Name );
Same as the previous one plus that when the Property “Name
” will get changed, the PropertyChanged
event will be raised for the welcomeMsg
too.
this.NotifyPropertyChange(model => model.Command).DependOn(model => model.Name);
As the Command Property in the viewmodel
is of type Command, so it will be the event CanExecuteChanged how will get fired when the property name changes.
- Add this attribute on the view model:
[ViewModel(typeof(MainPageViewModelConfiguration))]
so the MainviewModel
now looks like this:
[ViewModel(typeof(MainPageViewModelConfiguration))]
public class MainPageViewModel
{
[DefaultValue("xx")]
public string Name { get; set; }
public string WelcomeMsg => $"Hello {Name}";
public ICommand Command { get; }
public MainPageViewModel()
{
Command = new Command(() => { }, () => Name.Length > 3);
}
}
- Finally the view:
<StackLayout>
<Entry Text="{Binding Name , Mode=TwoWay}" />
<Label Text="{Binding WelcomeMsg}" />
<Button Text="Submit" Command="{Binding Command}" />
</StackLayout>
As you may noticed, I have used the DefaultValue Attribute in the view model, it is one of the side advantages of xamarin.MetaProgramming
we have implemented the required logic to allow the DefaultValue
Attribute to work.
Thanks to everyone who is sharing my blog posts, last week we got featured in feedspot.com as one of the best 60 Xamarin blogs and Postsharp offered me a free license, I hope to hear more from you in the comments.