Eduardo Rosas' Blog

Learn Azure, Xamarin, WPF, and more!

Xamarin Forms MVVM - ICommand

Photo 3-22-18, 4 44 47 PM.jpg

MVVM

ICommand Interface

In the previous post, we talked about the INotifyPropertyChanged, and I gave a small introduction about the MVVM architectural pattern, and how it will allow you to structure your code in a way that will make it easy to maintain, easy to scale and easy to reuse.

This post will be about the ICommand interface. If you have created Xamarin Forms applications before, this interface will help you replace all the event handlers you have in the code behind for button clicks (and other events) for code that you can now move over to your ViewModel.

I will continue to use the previous project that I used in the previous post, which added to values together and expand the functionality. This time, the Result property won't automatically be returning the addition, it will need a setter that will be called from certain methods depending on which method is pressed (we will add more than one button).

Changing the current functionality a bit

Currently, we have a Result property inside our ViewModel class, which is by default returning the addition of the other two properties, has no setter, and it is the other properties the ones that call the OnPropertyChanged event for this property, not the property itself. If we want to add an addition, subtraction, multiplication and division button to the app, so the user can actually select the operation that will be executed, we will need some changes.

private double numberOne;

public double NumberOne
{
    get { return numberOne; }
    set
    {
        numberOne = value;
        OnPropertyChanged("NumberOne");
    }
}

private double numberTwo;

public double NumberTwo
{
    get { return numberTwo; }
    set
    {
        numberTwo = value;
        OnPropertyChanged("NumberTwo");
    }
}

private double result;

public double Result
{
    get { return result; }
    set
    {
        result = value;
        OnPropertyChanged("Result");
    }
}

I only did two changes here:

  1. The NumberOne and NumberTwo properties no longer call the OnPropertyChanged for the Result property
  2. The Result property now has a setter (which of course calls the OnPropertyChanged for itself)

The Functionality

These changes will now allow us to set the Result depending on the button that is pressed. We can actually add the functionality already. I will create a Model class that will contain that functionality, it will have four methods, for each of the four basic operations that my "calculator" will be able to do:

public class Model
{
    public static double Add(double n1, double n2)
    {
        return n1 + n2;
    }

    public static double Sustract(double n1, double n2)
    {
        return n1 - n2;
    }

    public static double Multiply(double n1, double n2)
    {
        return n1 * n2;
    }

    public static double Divide(double n1, double n2)
    {
        return n1 / n2;
    }
}

This Model class then contains in itself the whole functionality, but we do have to use it from the ViewModel. I have then made all the members static (and of course public) so I can access them easily from the ViewModel class without the need to create an instance.

In the ViewModel I will create some other methods that will seem a bit redundant, but I want you to understand how the layer separation between the Model and the ViewModel would take place in larger applications. In these new methods I will call the methods from the Model, and will assign the result to the Result property.

public void Add()
{
    Result = Model.Add(NumberOne, NumberTwo);
}

public void Sustract()
{
    Result = Model.Sustract(NumberOne, NumberTwo);
}

public void Multiply()
{
    Result = Model.Multiply(NumberOne, NumberTwo);
}

public void Divide()
{
    Result = Model.Divide(NumberOne, NumberTwo);
}

Because these methods will now be changing the value from Result, and Result is calling the OnPropertyChanged method, they will effectively notify the View of the changes, all that's is left is actually create those commands.

ICommand

I will be creating a command for each of the buttons I will have, and while there is a more straightforward way to define them, I will show you the full implementation so you understand everything that goes behind these commands.

I will be creating a folder, called Commands, inside my project. Inside, I will start by creating an AddCommand class. This class will implement the ICommand interface. If you read the previous post, you now know how Visual Studio can help you implement an interface, if not, simply type 'control' + '.' while you have your cursor on the interface name and select implement interface (you may first need to add a using directive to System.Windows.Input

2018-03-22 17_09_11-MVVM - Microsoft Visual Studio.png

The implementation, as you can see in that image as well, will add three members, an event, and two methods. Here is what they will do:

  • CanExecuteChanged event: See the CanExecute to understand a bit more, but this will notify the View that Binds this command if the command's ability to execute changed (the value is boolean, so from true to false or from false to true)
  • CanExecute method: Defines if the element binding the command can execute the command or not. Depending on the element, this may actually disable the element if the method returns false. For example, the button could be grayed out, disabled, so the user cannot press it. Until something changes, the CanExecute may return true, enabling the button again.
  • Execute method: Executes the functionality, here is where we will need, in the case of this particular Command, to call the Add button from the ViewModel.

In our case we won't need nothing fancy here, I will need a property of type ViewModel (which will be set to a value from a constructor that I will also add) so I can access the Add method, and I will be calling that method from the Execute method, as well as always returning true for the CanExecute:

public class AddCommand : ICommand
{
    public ViewModel ViewModel { get; set; }

    public event EventHandler CanExecuteChanged;

    public AddCommand(ViewModel vm)
    {
        ViewModel = vm;
    }

    public bool CanExecute(object parameter)
    {
        return true;
    }

    public void Execute(object parameter)
    {
        ViewModel.Add();
    }
}

Notice that the constructor will be receiving a parameter of type ViewModel, which will be assigned to the ViewModel Property. This is the whole command, all that's left is to add a property of type AddCommand to the ViewModel.

The View Model

From the View Model, we are already binding the three properties to the corresponding entries and labels in the View, we will need something similar with the Command, so a new property must be created. This one, must be initialized from the constructor of the ViewModel, notice that the constructor is receiving the ViewModel itself through the 'this' keyword:

public AddCommand AddCommand { get; set; }

public ViewModel()
{
    AddCommand = new AddCommand(this);
}

With this, I will be able to bind this to any new method that I create. I will then add a button to my interface, and set its command to bind to this AddCommand property that I have just added to the ViewModel class, which remember, is the context for the entire StackLayout:

<Button Text="Add"
        Command="{Binding AddCommand}"/>

Just like this, when the button is pressed, the AddCommand command will be executed, the Execute method will be called, which will call the Add method from the VM, which will set the Result property (firing the OnPropertyChanged) to the result returned from the Add method from the Model class.

The result label then, will be now updated after the button is pressed:

In the same way, you could add the commands for subtraction, multiplication and division. Check this repository, specially the ICommand branch, to take a look at the full project:


This topic, along with many many others, is covered in greater depth in my 25-hour long "The Complete Xamarin Developer Course: iOS and Android" course, which you can practically steal from me by