Xamarin.Forms: ListView Simple MVVM Binding Example

Friday, February 24, 2017



Continuing this series of simple MVVM bindings in Xamarin.Forms. In this tutorial I will make simple ListView binding in XAML.

Run your Visual Studio and create new Xamarin.Forms project, add Views, Models and ViewModels folders.

This will be simple one page app with ListView as a main control on the page/view and we will demonstrate how to make simple MVVM binding in ListView.

Scenario for this demo is: At constructor of ViewModel we will set some default values, and after couple of seconds using web services we will "grab" some other data and store (update) it in our list, and all of this will be inside of our view model with zero lines of code in code-behind file of our view/page.


For this example I will use Xamari.Forms PCL for Core of the App.

And for hosting simple API for my HTTP GET calls I will use free service called myjson.com it is very nice and handy for tutorials or small testings.

This is how my project structure looks like for now:



In Models folder now I will add simple class "Car" with three properties: CarID, Make and YearofModel.

... and it looks like this:

Now I will add my page called CarsPage inside of Views folder, like this:


As you can see we have very simple page with list view in it, list view has ItemTemplate and DataTemplate in side of it. ListView controls is binding to Items of type ObservableCollection and the data in side of list view will be binding to the properties of the class Car to the two properties Make and YearOfModel. If this is little confusing for you I suggest you to take a look at my early tutorials about bindings and hope that will be helpful for you.

Now when we have this page we need a view model which we will make logic for updating the list data and we need view model in order to follow MVVM rules in our app.

Maybe in future I will make my own blog post about why to use MVVM and for now I suggest you to take a look at this great answers on Stack Overflow. Why use MVVM?

.. Now lets create that view model called CarsViewModel.cs and it looks like this:
I strongly recommend you to take a look at my blog post: Xamarin.Forms Simple MVVM Binding Example

In that blog post I am explaining the INotifyPropertyChanged and OnPropertyChanged in more detail way, and ObservableCollection is already implementing the INotifyPropertyChanged, so on Add, Remove... INotifyPropertyChanged will be triggered and UI will be updated.

INotifyPropertyChanged is interface which this view model class will implement and it have OnPropertyChanged  method which we will be calling on the spots where we are updating the data and OnPropertyChanged method will be changing the value of our controls with zero of code in the code behind classes.

Now when we have this view model (in which we will add couple of lines of code later), we need to connect with our page and we can do that in the CarPage.xaml.cs like this (at line 19.) :



Now we can run our app and hopefully we will have list of two cars displayed. (Also do not forget to set in your App.xaml.cs: main page to be: MainPage = new CarsExample.Views.CarsPage(); or navigate to the CarsPage as you want.)

Here is our app and how CarsPage looks like:




In the Utils folder I will add the class called MyHTTP and this will be my helper class for calling the web service to get data that will be in the list after update. So add that class and it looks something like this:

Maybe this approach will be strange for you but this is a way that I like to use async methods:

If you have any issue with HTTPClient you can solve this by adding Microsoft.Net.Http nuget package in your project PCL.

After this we need to make API Call in the our view model class like this: (from line 46. to 52.)

If everything is OK, now we can run our app, and result need to be that we have our list view with two default values and after couple of seconds (to make api call and deserialize data) we will have updated list with new values. (Do not forget to turn on wi fi on your device.)

I will make a gif demo for this app, so you can see here how it will look like when you run it on your pc and device.

As you can see on the gif down bellow there is a list of default values after couple of seconds list is updated and all that from our view model with minimum of lines of code at the code-behind.

Demo (gif):




As always demo code will be on the my GitHub, here at almirvuk/Xamarin.Forms_MVVM_ListView_Binding.Example


Hope that this tutorial was helpful for you in your process of development or learning Xamarin.Forms, if it is share it with your colleagues and good luck with development.

Best regards! Almir Vuk https://almirvuk.blogspot.com/

You Might Also Like

12 comments

  1. Almir, thanks for spending the time doing this. Nice tutorial.

    ReplyDelete
    Replies
    1. Thank you for the comment I am glad that this blog post was helpful for you!

      Delete
  2. powerful Tutorial,Thanks alot...i liked your Master-Detail Page Navigation menu in Xamarin.Forms too

    ReplyDelete
  3. Thanks for tutorial, very goof. Reading "https://developer.xamarin.com/guides/xamarin-forms/enterprise-application-patterns/" I very confuse about navigation between ViewModel, so I hope that your next tutorial regard this argument.

    ReplyDelete
  4. love it, but the view model picture isn't loading for me :(

    ReplyDelete
  5. Hello, I am trying your sample and I get this warning from Visual Studio: "Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call".

    It is just a warning, so the code compiles right. But the execution in my case fails. Although the 2 default values show correctly, the 3 values supposed to be retrieved from the API never show in the screen.

    Do you think there could be some deadlock the code is incurring in?

    Thank you in advance and also for the post.

    ReplyDelete
    Replies
    1. Hi,

      Can you post your code snippet from ViewModel, so we can see where the problem is.

      Best regards!

      Delete
  6. Here is my code (almost exactly the same as yours):

    using RestDem.Models;
    using RestDem.Utils;
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Linq;
    using System.Runtime.CompilerServices;
    using System.Text;
    using System.Threading.Tasks;

    namespace RestDem.ViewModels
    {

    public class CarsViewModel : INotifyPropertyChanged
    {

    private ObservableCollection items;

    public event PropertyChangedEventHandler PropertyChanged;

    public ObservableCollection Items
    {
    get { return items; }
    set
    {

    items = value;
    }
    }


    public CarsViewModel()
    {

    // Here you can have your data form db or something else,
    // some data that you already have to put in the list
    Items = new ObservableCollection() {
    new Car()
    {
    CarID = 1,
    Make = "Tesla Model S",
    YearOfModel = 2015
    },
    new Car()
    {
    CarID = 2,
    Make = "Audi R8",
    YearOfModel = 2012
    },

    };

    // Web service call to update list with new values
    MyHTTP.GetAllNewsAsync(list =>
    {
    foreach (Car item in list)
    Items.Add(item);
    });
    }
    }
    }

    I had to add the "public event Property..." so the code compiled, otherwise it said that CarsViewModel didn't implement interface member INotifyPropertyChanged. So once I added this extra line, the code compiles right, but never shows any entry in the list.

    If, trying another way, I remove the ": INotifyPropertyChanged" from the definition of CarsViewModel (and then don't need the former extra line), the the code compiles right again, show the two default values, but never shows the values to retrieve from the API url.

    Thanks for your attention.

    ReplyDelete
    Replies
    1. Have you tried to debug your app just to be sure that you fetch the data from api?

      Delete
  7. I will thank you. I think somehow the data are not being fetched.

    ReplyDelete

Instagram