Xamarin Forms i MVVMLight

Chcecie napisać aplikacje mobilną? Pokażę wam jak to zrobić w Xamarin Forms razem z MVVMLight

Witajcie cześć i czołem pytacie skąd się wziąłem… A na imię mi Xamarin Forms razem z MVVMLight i pokrótce chciałbym wam pokazać jak łatwo można użyć wzorca Model-View-ViewModel w aplikacji mobilnej.

Instalacja MVVMLight

MVVMLight jest pakietem NuGet, który może pobrać używając konsoli NuGet Package Manager Console.NuGet Package Manager Console

W tym celu w naszej aplikacji należy otworzyć konsolę NuGet Package Manager w Visual Studio, szukam pakietu MvvmLightLibs i instalujemy go w naszych wszystkich projektach.

Konfiguracja kontenera Inversion Of Control

Na początek czeka nas odrobina konfiguracji naszego nowego projektu. Na razie konfiguracja kontenera IoC wygląda na nadmiarową pracę ale zapewniam was, że później to zaprocentuje w postaci łatwego przełączania się pomiędzy kodem „produkcyjnym” i „mock”.

Na początek stwórzmy prosty ViewModel o nazwie MainViewModel, który będzie korzystał z interfejsu IAccountService.

MainViewModel

using Client_BankOfSanEscobar.Interfaces;
using Client_BankOfSanEscobar.Models;
using GalaSoft.MvvmLight;
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;

namespace Client_BankOfSanEscobar.ViewModels
{
    public class MainViewModel : ViewModelBase
    {
        private readonly IAccountService accountService;

        public string Title { get; set; }
        public ObservableCollection<Account> Accounts { get; set; }
        public float AvailableBalance { get; set; }
        
        public MainViewModel(IAccountService accountService)
        {
            if (accountService == null)
                throw new ArgumentNullException("accontService");

            this.accountService = accountService;

            Task.Run(() => Init());
        }

        public async Task Init()
        {
            if (Accounts != null)
                return;

            Accounts = new ObservableCollection<Account>(await accountService.GetAll());
            foreach (var balance in Accounts.Select(a => a.Balance))
                AvailableBalance += balance;
        }
    }
}

Teraz stwórzmy interfejs IAccountService

IAccountService

using Client_BankOfSanEscobar.Models;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Client_BankOfSanEscobar.Interfaces
{
    public interface IAccountService
    {
        Task<IEnumerable<Account>> GetAll();
    }
}

oraz jego implementację w postaci obiektu „mock”

AccountServiceMock

using Client_BankOfSanEscobar.Interfaces;
using Client_BankOfSanEscobar.Models;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Client_BankOfSanEscobar.Mock
{
    public class AccountServiceMock : IAccountService
    {
        public Task<IEnumerable<Account>> GetAll()
        {
            const int numberOfAccountsToGenerate = 4;
            return Task.Run(() => GenerateAccounts(numberOfAccountsToGenerate));
        }

        private IEnumerable<Account> GenerateAccounts(int numberOfAccounts)
        {
            var accounts = new List<Account>(numberOfAccounts);
            for (int i = 0; i < numberOfAccounts; i++)
            {
                accounts.Add(new Account(name: $"Account {i}", number: $"26200400001545234{i}", balance: 150.56f + i));
            }
            return accounts;
        }
    }
}

Uff prawie dobrnęliśmy do końca jeszcze tylko….Konfiguracja kontenera IoC.

W naszym kodzie użyjemy myśli technologicznej firmy Microsoft w postaci ServiceLocator, a implementacja wygląda następująco. Niektórzy twierdzą, że jest fajny The Service Locator Pattern, a inni twierdzą, że nie Antywzrorzec Service Locator.

Locator

using Client_BankOfSanEscobar.Interfaces;
using Client_BankOfSanEscobar.Mock;
using Client_BankOfSanEscobar.ViewModels;
using GalaSoft.MvvmLight.Ioc;
using Microsoft.Practices.ServiceLocation;

namespace Client_BankOfSanEscobar
{
    public class Locator
    {
        public Locator()
        {
            ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

            //ViewModels
            SimpleIoc.Default.Register<MainViewModel>();

            //Services
            SimpleIoc.Default.Register<IAccountService, AccountServiceMock>();
        }

        public MainViewModel Main
        {
            get
            {
                return ServiceLocator.Current.GetInstance<MainViewModel>();
            }
        }
    }
}

Musimy jeszcze zainicjować nasz Locator możemy to zrobić w klasie App.cs

App

using Xamarin.Forms;

namespace Client_BankOfSanEscobar
{
    public partial class App : Application
    {
        private static readonly Locator locator = new Locator();

        public static Locator Locator
        {
            get
            {
                return locator;
            }
        }

        public App()
        {
            InitializeComponent();

            MainPage = new Views.MainPage();
        }
    }
}

Cała konfiguracja i robota papierkowa za nami teraz możemy dojść do mięcha.
Mięcho

Binding ViewModel do UI

A więc żeby użyć naszego nowego pachnącego ViewModel należy go „podłączyć” do naszego widoku. Robimy to poprzez odpowiednie skonfigurowanie BindingContext.

        public MainPage()
        {
            InitializeComponent();
            BindingContext = App.Locator.Main;
        }

Podsumowanie

A więc jak widzicie użycie MVVMLight i Xamarin Forms jest możliwe. Na początku konfiguracja i powiązanie wszystkiego zajmuje trochę czasu ale w przyszłości będzie miało to plusy. Cały kod źródłowy możecie znaleźć na GitHub

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *