Tag Archive : MVVM

/ MVVM

There are many ways to write an app and many patterns to follow. Some are very useful, others a bit less but there is one that you should always use MVVM, Model View View Model. It allows you to separate your apps in three main parts or layers:

Model: Your data

View: Your UI

View Model: Your logic

This pattern is brilliant so you should really use it. In it, your View knows nothing about the logic of your app and your ViewModel knows nothing about the UI, but they communicate through a mechanism called Data Binding.

<Label Text="{Binding MyTitle}"/>

In this quick example we have associated the text property of our Label to the property “MyTitle” in our ViewModel. Easy, isn’t it?


The problem

MVVM is great (and you should really use it) BUT the data binding has two big problems:

  • Because they are resolved at run-time, you have no validation at compile-time. It means that if in the previous example, instead of MyTitle you write MyTile, you code will compile fine and you will be able to run your app BUT you will not see the text in your label.
  • As we said, they are resolved at run-time through a mechanism called reflection. Reflection is cool but it has an high overhead cost, so every time you load a page with some bindings, your app will consume time.

The solution

Luckily there is a solution to enjoy MVVM and Data Binding, without having to worry about performances and the solution is Compiled Bindings.

To enable the Compiled Binding you have to do two quick steps:

  • Enable XAML compilation.
  • Set the correct x:DataType attributes.

It’s incredibly easy to do it an it’s easier to do that to explain so I’m going to show you how to do it with an example.


If you are starting a new Xamarin.Forms project, the template already has the XAML compilation enabled, but if you need to enable it you can add this attribute:

[XamlCompilation(XamlCompilationOptions.Compile)]

to your page class in your XAML code behind. So the class of your page will be similatr to this:

[XamlCompilation (XamlCompilationOptions.Compile)]
public class HomePage : ContentPage
{
    //Add your content here...
}

Very easy. Now let’s see how to set the correct x:DataType.

First of all, let’s say that our View is called MyExamplePage and our ViewModel is called MyExampleViewModel and that our page has a label with a binding:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:viewModels="clr-namespace:XamarinExpert.ViewModels;assembly=XamarinExpert"
             x:Class="XamarinExpert.Views.MyExamplePage">
    <ContentPage.BindingContext>
        <viewModels:MyExampleViewModel />
    </ContentPage.BindingContext>
    <ContentPage.Content>
        <StackLayout>
            <Label Text="{Binding MyTitle}"
                VerticalOptions="CenterAndExpand" 
                HorizontalOptions="CenterAndExpand" />
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

This is a perfectly correct XAML and if we build and start it, it will run. If the property MyTitle exists in MyExampleViewModel, then we will be able to see the text.

Now let’s add the x:DataType  to enable the Compiled Data Binding. The code will be:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:viewModels="clr-namespace:XamarinExpert.ViewModels;assembly=XamarinExpert"
             x:DataType="viewModels:MyExampleViewModel"
             x:Class="XamarinExpert.Views.MyExamplePage">
    <ContentPage.BindingContext>
        <viewModels:MyExampleViewModel />
    </ContentPage.BindingContext>
    <ContentPage.Content>
        <StackLayout>
            <Label Text="{Binding MyTitle}"
                VerticalOptions="CenterAndExpand" 
                HorizontalOptions="CenterAndExpand" />
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

the only thing we have added is:

x:DataType="viewModels:MyExampleViewModel"

I told you that it was easy.

Now we have obtained two great things:

  • Our code will be faster as we don’t have to use reflection anymore.
  • When we compile the code, the compiler will check if our properties (MyTitle in this case) are actually present in our ViewModel. If not, the compiler will inform you of the error and you will be able to quickly fix it.

Performances

I haven’t done any precise test but I’ve actually seen that enabling the Compiled Binding, made my app UI faster and smoother. So they work. Anywaythere are some numbers, According to Microsoft and Xamarin:

  • A  compiled binding with property-change notification is resolved approximately 8 times quicker than a classic binding.
  • A compiled binding without property-change notification is resolved approximately 20 times quicker than a classic binding.
  • Setting the BindingContext on a compiled binding that uses property change notification is approximately 5 times quicker than setting the BindingContext on a classic binding.
  • Setting the BindingContext on a compiled binding that doesn’t use property change notification is approximately 7 times quicker than setting the BindingContext on a classic binding.

Few Tips

  • Always use the Compiled Bindings
  • If possible, set the x:DataType attribute at the same level in the view hierarchy as the BindingContext is set. (When you set the BindingContext, set the x:DataType too)
  • The x:DataType attribute can be re-defined at any point in a view hierarchy. For example you can set the x:DataType at the ContentPage level (like we did before) and then set it again on a label or on a CollectionView (Really you should use them as I wrote here).
  • If for some reason in your view you need to disable the Compiled Bindings, you can set the x:DataType to null, for example:
<StackLayout x:DataType="{x:Null}">
    <Label Text="{Binding MyTitle}" />
</StackLayout>

Conclusion

Compiled Bindings are extremely useful for two main reasons, they are faster and they discover a lot of problems at compile-time. You should really always use them.

As usual, if you like the article or you have questions, leave a comment down here.

The MVVM and Fody

The MVVM (Model, View, ViewModel) pattern helps you to organise and structure your code to create better apps.With this pattern you can split your code in 3 main parts:Model: Where you put your dataViewModel: It’s the logic of your app and a link between the Model and the ViewView: It’s the UI of your app (usually written in XAML) The main idea is to keep model, logic and UI completely separated.  And let’s be honest, this is how you should write your app.The interaction between the View and the ViewModel is done with the Data Binding

The Data Binding

The Data Binding is the connection between the UI and ViewModel of your app.You use it to connect a control (eg. a text) of your UI to your logic.Let’s say that we have an Entry (where a user can insert a text) and we want to link it to our ViewModel.We have something like this:in our UI (the View):

<Entry Text="{Binding Username}" Placeholder="Your username" />

In our ViewModel:

//OUR PROPERTY
        private string _username;

        public string Username
        {
            get => _username;
            set
            {
                _username = value;
                OnPropertyChanged();
            }
        }

In this case we have linked the Entry in our UI with the property (Username) in our ViewModel. When the user writes something in this entry, the Username value will change accordingly. And because the link is bidirectional (by default but you can change this behaviour), if we change the property value (eg. loading it from a database) the UI will change accordingly. It’s amazing. Isn’t it?

How to improve the code

To make a link between the UI and the ViewModel we need to use properties. Inside the set of each property we must call OnPropertyChanged (so our ViewModel must implement the INotifyPropertyChanged interface).It works, that’s great, but in a View usually we have a lot of interactive controls and for each of these we should need a property so there are cases where in our ViewModel we have many properties and you can imagine that the code is not readable anymore.Can we improve this? YES!

FODY

Fody is a library for IL weaving (the process to manipulate/inject code in IL). To put it easy, Fody will update automatically our code for us adding new cool features. In this case we are interested in a particular nuget plugin for Fody called PropertyChanged. This plugin will “Inject code which raises the PropertyChanged event, into property setters of classes which implement INotifyPropertyChanged.”What it means, is that we don’t have to explicitly call OnPropertyChanged() but we can instead use Auto-Properties.We can therefore convert our previous Username property to this:

public string Username { get; set; }

We have reduced the number of lines of code from 10 to 1. IMPRESSIVE!. Let’s say that in our ViewModel we have 20 properties, we have 200 lines of code only to declare our properties. With Fody & PropertyChanged plugin we can have only 20 lines of code instead of 200, saving 180 lines! Not Bad!

How to add it to your project

The process in incredibly easy:

  1. In your project install the Fody plugin (only in your PCL/.Net Standard project, in case of Xamarin, you don’t need to install in the Android, iOS,UWP projects): Fody
  2. Install the PropertyChanged plugin (only in your PCL/.Net Standard project): PropertyChanged
  3. Add to your PCL/.NetStandard project a new file called FodyWeavers.xml
  4. Open the file and change its content to:
<?xml version="1.0" encoding="utf-8" ?>
<Weavers>
    <PropertyChanged/>
</Weavers>

IMPORTANT: PropertyChanged will convert your properties only inside the viewmodels that implement the INotifyPropertyChanged interface. So don’t forget to do it in your ViewModels where you want to use Fody PropertyChanged:

public class LoginViewModel : INotifyPropertyChanged

How to add a Checkbox in Xamarin.Forms

May 14, 2019 | Tutorial | No Comments

We are going to show step by step how to create a Checkbox for Xamarin.Forms with a very simple code without the use of Custom Renderers.This checkbox will work on every platform: Android, iOS, UWP… and the final result will be something like:

Checkbox disabled
Checkbox disabled
Checkbox enabled
Checkbox enabled

There are just two steps you need to do:

  • Add your images
  • Create the Checkbox class

After the two steps, I’m going to show you a small example on how to use this checkbox.

Add the Checkbox images

The first thing to do is to choose two images for the checkbox, one enabled and the other disabled (similat to the ones you can see in the previous images).

Add the images as embedded resources
Add the images as embedded resources

Create an Images folder inside your PCL/.NetStandard project and add the two images in it. Be sure to set the two images as Embedded Resources (as in the previous image).

Add the Checkbox class

Now it’s time to create our checkbox class. Inside your PCL/.NetStandard project create the file Checkbox:

using System;
using System.Windows.Input;
using Xamarin.Forms;

namespace Tutorial02
{
    public class Checkbox : StackLayout
    {
        public event EventHandler CheckedChanged;
        private readonly Image _image;

        private readonly Label _label;
        //CHANGE THESE 2 STRINGS ACCORDING TO YOUR NAMESPACE AND IMAGE

        static string imgUnchecked = "Tutorial02.Images.unchecked.png";
        static string imgChecked = "Tutorial02.Images.checked.png";
        public static readonly BindableProperty CommandProperty = BindableProperty.Create("Command", typeof(ICommand), typeof(Checkbox));

        public static readonly BindableProperty CheckedProperty = BindableProperty.Create("Checked", typeof(Boolean?), typeof(Checkbox), null,
            BindingMode.TwoWay, propertyChanged: CheckedValueChanged);

        public static readonly BindableProperty TextProperty =
            BindableProperty.Create("Text", typeof(String), typeof(Checkbox), null, BindingMode.TwoWay, propertyChanged: TextValueChanged);

        public ICommand Command
        {
            get => (ICommand) GetValue(CommandProperty);
            set => SetValue(CommandProperty, value);
        }

        public Boolean? Checked
        {
            get => (bool?) GetValue(CheckedProperty);
            set => SetValue(CheckedProperty, value);
        }

        public String Text
        {
            get => (string) GetValue(TextProperty);
            set => SetValue(TextProperty, value);
        }

        public Checkbox()
        {
            Orientation = StackOrientation.Horizontal;
            BackgroundColor = Color.Transparent;
            _image = new Image()
                {Source = ImageSource.FromResource(imgUnchecked), HeightRequest = 35, WidthRequest = 35, VerticalOptions = LayoutOptions.Center};
            var tg = new TapGestureRecognizer();
            tg.Tapped += Tg_Tapped;
            _image.GestureRecognizers.Add(tg);
            Children.Add(_image);
            _label = new Label() {VerticalOptions = LayoutOptions.Center};
            _label.GestureRecognizers.Add(tg);
            Children.Add(_label);
        }

        private void Tg_Tapped(object sender, EventArgs e)
        {
            Checked = !Checked;
        }

        private static void CheckedValueChanged(BindableObject bindable, object oldValue, object newValue)
        {
            if (newValue != null && (Boolean) newValue) ((Checkbox) bindable)._image.Source = ImageSource.FromResource(imgChecked);
            else ((Checkbox) bindable)._image.Source = ImageSource.FromResource(imgUnchecked);
            ((Checkbox) bindable).CheckedChanged?.Invoke(bindable, EventArgs.Empty);
            ((Checkbox) bindable).Command?.Execute(null);
        }

        private static void TextValueChanged(BindableObject bindable, object oldValue, object newValue)
        {
            if (newValue != null) ((Checkbox) bindable)._label.Text = newValue.ToString();
        }
    }
}

Your are now ready to use the checkbox in your apps and it will work for every platform supported by Xamarin. GREAT!Now I’ll show you a small example on how to use this checkbox inside your App:

Add the Checkbox to your ContentPage

Inside the our ContentPage we have set the ViewModel and then added the checkbox:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"             
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"             
             xmlns:local="clr-namespace:Tutorial02"
             xmlns:viewModel="clr-namespace:SafePhoto2.ViewModel;assembly=SafePhoto2"
             x:Class="Tutorial02.MainPage">
    <ContentPage.BindingContext>
        <viewModel:MainViewModel />
    </ContentPage.BindingContext>
    <local:Checkbox VerticalOptions="CenterAndExpand"                     
                    HorizontalOptions="CenterAndExpand"                     
                    Checked="{Binding IsChecked}"                     
                    Text="{Binding TextCheckBox}"                     
                    Command="{Binding OnCheckedChanged}">

    </local:Checkbox>
</ContentPage>

The checkbox has two important properties: Checked and Text.

  • Checked is bound to the IsChecked property of the ViewModel and indicates if the checkbox is checked or not
  • Text is bound to the TextCheckBox property of the ViewModel and is the text that appears next to the CheckBox image

In case you want to execute an action after the status of the checkbox is changed, you can use Command  (bound to the OnCheckedChanged inside the ViewModel) otherwise you can remove it from your XAML.

Create the ViewModel

The ViewModel used in our example is very easy and you can change it as you prefer. For this simple example we have just created a basic ViewModel:

using System.ComponentModel;
using System.Runtime.CompilerServices;
using Xamarin.Forms;

namespace Tutorial02
{
    public class MainViewModel : INotifyPropertyChanged
    {
        private bool _isChecked;
        private string _textCheckBox;
        public event PropertyChangedEventHandler PropertyChanged;

        public bool IsChecked
        {
            get => _isChecked;
            set
            {
                _isChecked = value;
                TextCheckBox = _isChecked ? "Is Enabled" : "Is Disabled";
                OnPropertyChanged();
            }
        }

        public string TextCheckBox
        {
            get => _textCheckBox;
            set
            {
                _textCheckBox = value;
                OnPropertyChanged();
            }
        }

        public Command OnCheckedChanged { get; set; }

        public MainViewModel()
        {
            OnCheckedChanged = new Command(OnCheckBoxChanged);
        }

        private void OnCheckBoxChanged()
        {
        }

        protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

As usual the ViewModel inherits from INotifyPropertyChanged.We have added two properties IsChecked and TextCheckBox and the Command OnCheckedChanged required only if we want to execute an action after the status of the checkbox is changed.When the IsChecked value changes, we set the Checkbox text to Is Enabled or Is Disabled according to its value.

Conclusion

In this tutorial we have seen how to create a Checkbox in Xamarin.Forms.The code is incredibly easy and ready to be used (you can copy and paste the code and it will work).If you have questions or doubts leave here a comment.If you need more info about the MVVM pattern in Xamarin you can check the Microsoft documentation here: https://docs.microsoft.com/en-us/xamarin/xamarin-forms/xaml/xaml-basics/data-bindings-to-mvvm

%d bloggers like this: