Archiwum kategorii: iOS

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

Visual Studio Mobile Center: Wprowadzenie

Wprowadzenie do Visual Studio Mobile Center, czyli czym to właściwie jest

W dzisiejszym artykule chciałbym was wprowadzić w temat czym jest Visual Studio Mobile Center, a więc zaczynajmy.

Czym jest Visual Studio Mobile Center

Visual Studio Mobile Center zostało zaprojektowane dla wszystkich aplikacji iOS i Android, stworzonych w Swift, Objective-C, Java, Xamarin lub React Native.

VSMC jest usługą, która ma zintegrować w jeden produkt HockeyApp, Xamarin Test Cloud i usługi backend świadczone w chmurze.

Została ona oficjalnie zaprezentowana na konferencji Connect() 2016.

Co działa

VSMC jest obecnie w fazie Preview dlatego też nie wszystko działa jak powinno lub czegoś brakuje. Poniżej krótka lista co obecnie działa.

  • Automatyczne budowanie po każdym pull request
  • Testy UI
  • Dystrybucja aplikacji do beta testów
  • Monitorowanie aplikacji
  • Analiza użycia
  • Podłączenie do backend np. Azure Mobile Apps, Databases, Identity

Mobile CI (Contiuous Integration), testy UI i analiza działania aplikacji

Według Wikipedia

Ciągła integracja – praktyka stosowana w trakcie rozwoju oprogramowania, polegająca na częstym, regularnym włączaniu (integracji) bieżących zmian w kodzie do głównego repozytorium. W praktyce, każdy członek zespołu programistycznego powinien przynajmniej raz dziennie umieścić wykonaną przez siebie pracę w repozytorium[1]. Niezbędnym elementem jest także zapewnienie poprawności kompilacji kodu po wykonaniu integracji.

W wypadku mobile CI było do tej pory trudne do osiągnięcia, zwłaszcza testy UI aplikacji były trudne do wykonania. Z pomocą w testach przyszedł Xamarin i jego Test Cloud gdzie używając Xamarin Studio mogliśmy nagrać „skrypt” do testowania UI. Natomiast do budowania aplikacji trzeba było używać narzędzi takich jak np. Jenkins.

W tej chwili otrzymujemy od Microsoft kompletne rozwiązanie w jednym pudełku.

Podsumowanie

Microsoft po przejęciu Xamarin mocno inwestuje w rozwój platformy mobile i ich wizji Mobile First Cloud First jednym z dzieci jest właśnie Mobile Center. Usługa wygląda ciekawie, działa i da się jej obecnie normalnie używać. Wersja produkcyjna ma ujrzeć światło dzienne w przyszłym roku.

Pomysł jest fajny ze względu na integracje kilku produktów w jeden. Zobaczymy jak to będzie działało w praktyce.

Dla zainteresowanych link do Visual Studio Mobile Center

Xamarin.iOS – Jak pokazać kontrolkę daty tak jak w kalendarzu iOS

Jest to tips & tricks działający dla Xamarin.iOS

W dzisiejszym odcinku chciałbym pokazać wam jak dodać kontrolkę daty „iOS style” (z takim fajnym rozwijaniem wierszy jak w np. w kalendarzu).

Xamarin.iOS – Jak pokazać kontrolkę daty tak jak w kalendarzu iOS

Ja w swoim przykładzie użyłem na Storyboard kontrolki TableViewController. Wywyższa kontrolka zapewnia nam funkcjonalność kontrolki TableView i ScrollView w jednym.

Następnie należy skonfigurować sekcji i wiersze, dodajemy kontrolkę DatePicker i wysokość wiersza ustawiamy na 216.

Reszta magii dzieje się w kodzie… Cały kod źródłowy można znaleźć na GitHub

Kod

using Foundation;
using System;
using UIKit;

namespace DatePickerDemo
{
    public partial class MainViewController : UITableViewController
    {
        private NSDateFormatter formatter;
        private bool showDatePicker;

        public MainViewController (IntPtr handle) : base (handle)
        {
            formatter = new NSDateFormatter();
            formatter.DateStyle = NSDateFormatterStyle.Short;
        }

        public override void ViewDidLoad()
        {
            base.ViewDidLoad();


            dateLabel.Text = formatter.ToString(datePicker.Date);
            datePicker.ValueChanged += DatePicker_ValueChanged;
        }

        public override nfloat GetHeightForRow(UITableView tableView, NSIndexPath indexPath)
        {
            nfloat rowHeight = tableView.RowHeight;

            if(indexPath.Section == 1 && indexPath.Row == 2)
            {
                rowHeight = 0;
            }

            if (showDatePicker && (indexPath.Section == 1 && indexPath.Row ==2))
            {
                rowHeight = 216;
            }

            return rowHeight;
        }

        public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
        {
            tableView.BeginUpdates();

            if (indexPath.Section == 1 && indexPath.Row == 1)
            {
                showDatePicker = !showDatePicker;
            }

            tableView.DeselectRow(indexPath, true);
            tableView.EndUpdates();
        }

        private void DatePicker_ValueChanged(object sender, EventArgs e)
        {
            dateLabel.Text = formatter.ToString(datePicker.Date);
        }
    }
}