rubezh-TWnlenfritplesuk

Xamarin.Forms, биндинги и MVVM по феншую

В этой статье мы поговорим с Вами о биндинге в Xamarin.Forms и создадим небольшую кросс-платформенную программу с использованием паттерна проектирования MVVM.

Внимание! Друзья, статья еще в процессе написания, поэтому еще не все мысли в ней изложены, а так же возможно изменение структуры и содержания со временем.

Как известно интерфейс в кросс-платформенном приложении на Xamarin.Forms можно реализовать на XAML, языке разметки широко известном среди разработчиков .NET WPF и SilverLight. XAML позволяет описать интерфейс программы единожды, а при компиляции программы интерфейс будет строиться из этого файла под каждую поддерживаемую платформу с использованием нативных или же дополнительных, описанных в плагинах, элементов управления. Так же XAML позволяет использовать привязки данных в интерфейсе, т.н. Data Bindings, что освобождает программиста от написания большого количества дополнительного кода, который обновляет интерфейс при загрузке модели и затем обновляет модель в соответствии с введенными в UI данными при сохранении модели. Стоит отметить, что в Xamarin.Forms, как и в WPF, широко используется паттерн проектирования MVVM (Model-View-ViewModel). Конечно никто не заставляет разрабатывать программу на Xamarin.Forms с применением этого паттерна, в некоторых ситуациях, когда программа имеет очень ограниченный функционал и занимает пару-тройку десятков строк кода, применение его избыточно. Но в более-менее крупных проектах он позволяет содержать код в порядке, зная какие из этих 3 частей за что отвечают - проще найти нужный участок кода, чем пересматривать смешанный код одной формы, который сразу занимается и UI, и загрузкой из БД/сети, и обработкой данных... Кроме того, применение MVVM, приближает проект к возможности применения автоматического тестирования, но об этом как-нибудь в следующий раз.

Сегодня мы рассмотрим некоторые нюансы использования Bindings в Xamarin.Forms, отличия от стандартного механизма в WPF, принцип разработки приложения с применением MVVM, и все это в ходе создания мини приложения, имеющего несколько несложных форм для редактирования и просмотра данных, которое затем можно будет собрать и запустить на устройствах с ОС iOS, Android и Windows.

Ну что, меньше лирики - приступим к созданию программы? Создадим проект в VisualStudio и выберем Cross-Platform App (Xamarin.Forms), название дадим SimpleApp:

simple app create project s1

Затем выбираем параметры будущего проекта:

simple app create project s2

Здесь необходимо выбрать целевые платформы, среди Android и iOS есть еще Windows(UWP). Т.е. мы получаем неплохой такой бонус от использования Xamarin - наше приложение может быть запущено еще и на устройствах (телефонах, планшетах и компьютерах!) с Windows. Хоть виндовсфоны сейчас достаточно редки стали, но эта целевая платформа подразумевает нечно большее: Universal Windows Platform (UWP) действительно юниверсал - один бинарник может быть выполнен и на телефоне и на ПК, где стоит Windows10. Не плохо, да?

UI Technology - это способ реализации интерфейса для нашего приложения в разных целевых платформах, то ли это будет Xamarin.Forms - и UI будет генерироваться на платформы из одного XAML файла, то ли это Native, и интерфейс придется создавать для каждой платформы уникальный, в родном исполнении - для Andriod в XML файлах, практически так же как и в AndroidStudio, для iOS придется использовать XCode на Mac.

Code Sharing Strategy - использование общего кода для приложения. Есть две стратегии:

Shared Project - использование одного кодового блока, который будет компилироваться вместе с приложением целевой платформы, как одно целое. В этом случае у кода имеется меньше ограничений на использование доступного конкретной платформе функционала, но для каждой из платформ в итоге придется вставлять условные блоки, типа "#if __ANDROID__ ... #endif", в которых будет находиться этот т.н. платформозависимый код (Platform specific code). В итоге получается достаточно запутанный код с обилием условных блоков.

.NET Standart - это новое поколение PCL библиотек (Portable Class Library или просто Picle). В этой библиотеке будет реализован общий для всех платформ функционал приложения, DAL (уровень доступа к данным), BL (бизнес логика). Имеются ограничения на использование специфичного для платформ функционала, поэтому все уникальные для платформ возможности выносятся в отдельные проекты и в библиотеку Picle импортируются с помощью механизма Dependency Injection.

В общем в этом окне выбираем все как показано на рисунке и жмем ОК.

Теперь получим болванку проекта из которой будем "вытачивать" наше приложение.

Шаблон приложения, созданный мастером проектов

Для следования паттерну MVVM нам необходимо организовать соответствующую структуру проекта, для этого нужно создать 3 папки в проекте SimpleApp: Models, Views, ViewModels (ПКМ по проекту SimpleApp, Добавить>Создать папку).

Начем с моделей.

using System;
using System.Collections.Generic;
using System.Text;

namespace SimpleApp.Models
{
    public class Auto: BaseModel
    {
        private String model;
        private String vin;
        private Int16 year;
        private Int32 mileage;
        private String description;

        public string Model
        {
            get { return model; }
            set { SetProperty(ref model, value); }
        }

        public Int16 Year
        {
            get { return year; }
            set { SetProperty(ref year, value); }
        }

        public Int32 Mileage
        {
            get { return mileage; }
            set { SetProperty(ref mileage, value); }
        }

        public string Vin
        {
            get { return vin; }
            set { SetProperty(ref vin, value); }
        }

        public string Description
        {
            get { return description; }
            set { SetProperty(ref description, value); }
        }
    }
}

Все верно, мы описываем класс автомобиль! Этот класс у нас наследуется от класса BaseModel, в котором описаны повторяющиеся в каждой модели поля и свойства, а так же имплементирован метод OnPropertyChanged из интерфейса INotifyPropertyChanged, необходимый для работы Binding-механизма XAML:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Text;

namespace SimpleApp.Models
{
    public class BaseModel : INotifyPropertyChanged
    {
        public BaseModel()
        {
            CreatedAt = DateTimeOffset.Now;
        }

        public int Id { get; set; }

        public DateTimeOffset CreatedAt { get; set; }

        public DateTimeOffset UpdatedAt { get; set; }

        protected bool SetProperty(
            ref T backingStore, T value,
            [CallerMemberName]string propertyName = "",
            Action onChanged = null)
        {
            if (EqualityComparer.Default.Equals(backingStore, value))
                return false;

            backingStore = value;
            onChanged?.Invoke();
            OnPropertyChanged(propertyName);
            return true;
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged([CallerMemberName]string propertyName = "")
        {
            var changed = PropertyChanged;
            if (changed == null)
                return;

            changed.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Для упрощения работы здесь реализован метод SetProperty, который устанавливает свойство класса в новое значение и вызывает метод OnPropertyChanged, для генерации события обновления значения. Поэтому в реализации модели достаточно написать так:

SetProperty(ref Property1, value);

Продолжение следует...

1 1 1 1 1 1 1 1 1 1 Рейтинг 82%

Печать E-mail

Добавить комментарий


Защитный код
Обновить