Xamarin Forms: Consumiendo un servicio web basado en JSON Parte 2: Creando el ViewModel

En este post nos enfocaremos a crear el ViewModel del proyecto. En primer lugar, crearemos una carpeta llamada ViewModel, donde alojaremos nuestro código correspondiente al ViewModel.

Crearemos una clase llamda MainPageViewModel, a la cual implementaremos la interfaz: INotifyPropertyChanged, de la siguiente manera:

using System.ComponentModel;
using System.Runtime.CompilerServices;
using JsonWebServices.Annotations;

namespace JsonWebServices.ViewModel
{
    public class MainPageViewModel : INotifyPropertyChanged
    {
        #region InotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;

        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        #endregion
    }
}

Para poder llevar a cabo la notificación de un cambio en una de las propiedades para poder comunicársela a la interfaz gráfica a través de un binding, debemos crear una propiedad  por cada valor que queramos notificar a la interfaz gráfica, seguido de la llamada al método OnPropertyChanged(), como en el siguiente ejemplo:

        private string _stationName;
        public string StationName
        {
            get
            {
                return _stationName;
            }

            set
            {
                _stationName = value;
                OnPropertyChanged();
            }
        }

Para ejemplos demostrativos, implementaremos las propiedades de StationName, Elevation, Temperature y Humidity, de la siguiente forma

        #region Properties
        private string _stationName;
        private int _elevation;
        private string _temperature;
        private int _humidity;
        public string StationName
        {
            get
            {
                return _stationName;
            }

            set
            {
                _stationName = value;
                OnPropertyChanged();
            }
        }
        public int Elevation
        {
            get
            {
                return _elevation;
            }

            set
            {
                _elevation = value;
                OnPropertyChanged();
            }
        }

        public string Temperature
        {
            get
            {
                return _temperature;
            }

            set
            {
                _temperature = value;
                OnPropertyChanged();
            }
        }

        public int Humidity
        {
            get
            {
                return _humidity;
            }

            set
            {
                _humidity = value;
                OnPropertyChanged();
            }
        }
        #endregion

Para la siguiente parte, debemos instalar un par de paquetes de nuget, los cuales puedes instalar a través de la Consola de paquetes de nuget, apuntando al proyecto Portable:

Screen Shot 04-25-16 at 09.46 AM

los cuales son:

Install-Package Microsoft.Net.Http

Install-Package Newtonsoft.Json

 

Posteriormente, debemos crear un método llamado GetWeatherAsync que se encargue de llevar a cabo la solicitud al sitio web, a través de una instancia de HttpClient. y su posterior deserialización de la siguiente forma:

        public async Task GetWeatherAsync(string url)
        {
            //Creamos una instancia de HttpClient
            var client = new HttpClient();
            //Asignamos la URL
            client.BaseAddress = new Uri(url);
            //Llamada asíncrona al sitio
            var response = await client.GetAsync(client.BaseAddress);
            //Nos aseguramos de recibir una respuesta satisfactoria
            response.EnsureSuccessStatusCode();
            //Convertimos la respuesta a una variable string
            var jsonResult = response.Content.ReadAsStringAsync().Result;
            //Se deserializa la cadena y se convierte en una instancia de WeatherResult
            var weather = JsonConvert.DeserializeObject<WeatherResult>(jsonResult);
            //Asignamos el nuevo valor de las propiedades
            SetValue(weather);
        }

Por último, agregaremos un método llamado SetValue, que nos servirá para actualizar las propiedades de la clase contenida en el ViewModel, de la siguiente forma:

        private void SetValue(WeatherResult weather)
        {
            var stationName = weather.WeatherObservation.StationName;
            var elevation = weather.WeatherObservation.Elevation;
            var temperature = weather.WeatherObservation.Temperature;
            var humidity = weather.WeatherObservation.Humidity;

            StationName = stationName;
            Elevation = elevation;
            Temperature = temperature;
            Humidity = humidity;
        }

El resultado final de la clase, deberá verse de la siguiente forma:

using System;
using System.ComponentModel;
using System.Net.Http;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using JsonWebServices.Annotations;
using JsonWebServices.Model;
using Newtonsoft.Json;

namespace JsonWebServices.ViewModel
{
    public class MainPageViewModel : INotifyPropertyChanged
    {
        #region Properties
        private string _stationName;
        private int _elevation;
        private string _temperature;
        private int _humidity;
        public string StationName
        {
            get
            {
                return _stationName;
            }

            set
            {
                _stationName = value;
                OnPropertyChanged();
            }
        }
        public int Elevation
        {
            get
            {
                return _elevation;
            }

            set
            {
                _elevation = value;
                OnPropertyChanged();
            }
        }

        public string Temperature
        {
            get
            {
                return _temperature;
            }

            set
            {
                _temperature = value;
                OnPropertyChanged();
            }
        }

        public int Humidity
        {
            get
            {
                return _humidity;
            }

            set
            {
                _humidity = value;
                OnPropertyChanged();
            }
        }
        #endregion

        #region Methods
        public async Task GetWeatherAsync(string url)
        {
            //Creamos una instancia de HttpClient
            var client = new HttpClient();
            //Asignamos la URL
            client.BaseAddress = new Uri(url);
            //Llamada asíncrona al sitio
            var response = await client.GetAsync(client.BaseAddress);
            //Nos aseguramos de recibir una respuesta satisfactoria
            response.EnsureSuccessStatusCode();
            //Convertimos la respuesta a una variable string
            var jsonResult = response.Content.ReadAsStringAsync().Result;
            //Se deserializa la cadena y se convierte en una instancia de WeatherResult
            var weather = JsonConvert.DeserializeObject<WeatherResult>(jsonResult);
            //Asignamos el nuevo valor de las propiedades
            SetValue(weather);
        }

        private void SetValue(WeatherResult weather)
        {
            var stationName = weather.WeatherObservation.StationName;
            var elevation = weather.WeatherObservation.Elevation;
            var temperature = weather.WeatherObservation.Temperature;
            var humidity = weather.WeatherObservation.Humidity;

            StationName = stationName;
            Elevation = elevation;
            Temperature = temperature;
            Humidity = humidity;
        }
        #endregion

        #region InotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;

        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        #endregion
    }
}

En la siguiente entrada, nos encargaremos de la parte de la vista. Cualquier duda o comentario, no dudes en escribirlo, y recuerda que el código fuente del ejemplo lo puedes encontrar aquí.

Saludos.

Deja un comentario