Объять необъятное, или как использовать несколько mvvm...

Post on 21-Mar-2017

239 Views

Category:

Software

5 Downloads

Preview:

Click to see full reader

TRANSCRIPT

#msdevcon

Community TrackОбъять необъятное, или как использовать несколько MVVM фреймворков в одном XAML проектеДенис ЦветцихРуководитель проектов, IceRockDev

#msdevcon

Цели

Зачем нужен MVVM

фреймворк

Как выбрать MVVM

фреймворк

Как использовать несколько

MVVM фреймворко

вЧем отличаются MVVM

фреймворкиКак выбрать MVVM

фреймворк для конкретной платформы

Какие MVVM фреймворки мы

использовали и для каких задач

Решение какой задачи упрощает

использование MVVM фреймворка

4

ОпросКто считает, что использовать несколько MVVM нельзя?Кто считает, что использовать несколько MVVM можно, но не использовал?Кто использовал несколько MVVM в одном проекте?

5

Зачем нужен MVVM фреймворк?НавигацияРеализация INPC (ViewModelBase)Команды Message Bus (EventAggregator, Messenger)

6

Зачем нужен MVVM фреймворк?НавигацияРеализация INPC (ViewModelBase)Команды Message Bus (EventAggregator, Messenger)

7

Подходы к навигацииView FirstViewModel First

Это не разные реализации паттерна MVVM,но разные подходы к навигации с использованием MVVM

8

ViewFirst: показать новую формуСоздать ViewСоздать ViewModel для ViewView.DataContext = ViewModelИнициализировать ViewModel

9

ViewFirst: показать новую формуNavigation.Show<ViewModel>(Value);илиNavigation.Show("View", Value);

Похоже на: http://address.ru/?arg=value

ViewFirst предлагает организовать навигацию аналогично веб-приложению

10

ViewModelFirst: показать новую формуСоздать ViewModelИнициализировать ViewModelСоздать View для ViewModelView.DataContext = ViewModel

11

ViewModelFirst: показать новую формуvar vm = Navigation.Get<ViewModel>();vm.Arg = Value;vm.Show();Аналогично окну WPF:var wnd = new Window();wnd.Arg1 = Value1;wnd.Show();

ViewModel First навигация аналогична навигации в настольных приложениях

12

ViewFirst vs ViewModelFirstViewFirst ViewModelFirstСоздать View Создать ViewModelСоздать ViewModel Инициализировать ViewModel

Инициализировать ViewModel Создать ViewView.DataContext = ViewModel View.DataContext = ViewModel

13

Выбор MVVM фреймворкаВыбираем MVVM фреймворк по реализованному подходу к навигацииНавигация MVVM фреймворка соответствует навигации в API выбранной технологииWPF: ViewModelFirst подход (MugenMvvmToolkit, ReactiveUI)UWP: ViewFirst подход (Prism)

14

Какие задачи решает MVVM фреймворк?Навигация КомандыПривязкиНа уровне ViewModel: передача событий между ViewModelНа уровне View: Binding в XAML

Разные задачи можно решать при помощи разных фреймворков!

15

Набор MVVM фреймворков для UWPНавигация – PrismСобственное расширение Prism для CompositeUI

Команды – ReactiveCommand из ReactiveUIПривязкиПривязки ViewModel: Не используем MessageBus (EventAggregator из Prism)Привязки ViewModel: ObservableForProperty, WhenAny из ReactiveUIПривязки View: альтернативный Binding из MugenMvvmToolkit

16

Prism - ViewFirst навигацияpublic interface INavigationService{

bool Navigate(string pageToken, object param);void GoBack();void GoForward();void ClearHistory();

}

17

Достоинства навигации PrismViewFirst подход, реализованный в Prism, соответствует API для навигации в UWPCompositeUI не реализован в Prism для UWP, но нужное решение есть по ссылкеhttps://github.com/denis-tsv/Prism.StoreApps.Extensions.Mvvm

18

ReactiveUI: команды и ViewModel привязкиpublic class LoginViewModel //: INotifyPropertyChanged{ public string Login { get; set; } // PropertyChanged

public string Password { get; set; } // PropertyChanged

public ICommand LoginCommand { get; private set; }

}

19

1. ObservableForProperty// ПодпискаIDisposable _subscription = this.ObservableForProperty(vm => vm.Login) .Subscribe(OnLoginChanged);

// Реакция на событиеprivate void OnLoginChanged (IObservedChange<LoginViewModel, String> change){ }

// Отписка_subscription.Dispose();

20

1. ObservableForProperty// ПодпискаIDisposable _subscription = this.ObservableForProperty(vm => vm.Login) .Subscribe(OnLoginChanged);

// Реакция на событиеprivate void OnLoginChanged (IObservedChange<LoginViewModel, String> change){ }

// Отписка_subscription.Dispose();

21

1. ObservableForProperty// ПодпискаIDisposable _subscription = this.ObservableForProperty(vm => vm.Login) .Subscribe(OnLoginChanged);

// Реакция на событиеprivate void OnLoginChanged (IObservedChange<LoginViewModel, String> change){ }

// Отписка_subscription.Dispose();

22

1. ObservableForProperty// ПодпискаIDisposable _subscription = this.ObservableForProperty(vm => vm.Login) .Subscribe(OnLoginChanged);

// Реакция на событиеprivate void OnLoginChanged (IObservedChange<LoginViewModel, String> change){ }

// Отписка_subscription.Dispose();

23

2. WhenAnyIDisposable _subscription = this.WhenAny( vm => vm.Login, vn => vm.Password, (login, password) => !string.IsNullOrEmpty(login.Value) && !string.IsNullOrEmpty(password.Value)) .Subscribe(OnCredentialsChanged);

24

2. WhenAnyIDisposable _subscription = this.WhenAny( vm => vm.Login, vn => vm.Password, (login, password) => !string.IsNullOrEmpty(login.Value) && !string.IsNullOrEmpty(password.Value)) .Subscribe(OnCredentialsChanged);

25

2. WhenAnyIDisposable _subscription = this.WhenAny( vm => vm.Login, vn => vm.Password, (login, password) => !string.IsNullOrEmpty(login.Value) && !string.IsNullOrEmpty(password.Value)) .Subscribe(OnCredentialsChanged);

26

Достоинства ReactiveUI привязокУдобное решение типовых задач:Подписка на изменение одного свойстваПодписка на изменение нескольких свойств

Уменьшается количество инфраструктурного кода, связанного с подписками и отписками

27

ReactiveCommandCanExecute == false, когда Логин и пароль пустыеВыполняется запрос аутентификации на сервер

28

3. ReactiveCommandpublic LoginViewModel(ILoginService loginService){ _loginService = loginService;

var canExecute = this.WhenAny(vm => vm.Login, vm => vm.Password, (login, password) => !string.IsNullOrEmpty(login.Value) && !string.IsNullOrEmpty(password.Value));

29

3. ReactiveCommandpublic LoginViewModel(ILoginService loginService){ _loginService = loginService; // Login(login, password)

var canExecute = this.WhenAny(vm => vm.Login, vm => vm.Password, (login, password) => !string.IsNullOrEmpty(login.Value) && !string.IsNullOrEmpty(password.Value));

30

3. ReactiveCommandpublic LoginViewModel(ILoginService loginService){ _loginService = loginService;

var canExecute = this.WhenAny(vm => vm.Login, vm => vm.Password, (login, password) => !string.IsNullOrEmpty(login.Value) && !string.IsNullOrEmpty(password.Value));

31

3. ReactiveCommand LoginCommand = ReactiveCommand.CreateAsyncTask (canExecute,

async _ => await _loginService.Login(Login, Password));

LoginCommand.Subscribe(OnLoginCompleted);} // of ctor

private void OnLoginCompleted(bool loginSuccessed){ }

32

3. ReactiveCommand LoginCommand = ReactiveCommand.CreateAsyncTask (canExecute,

async _ => await _loginService.Login(Login, Password));

LoginCommand.Subscribe(OnLoginCompleted);} // of ctor

private void OnLoginCompleted(bool loginSuccessed){ }

33

3. ReactiveCommand LoginCommand = ReactiveCommand.CreateAsyncTask (canExecute,

async _ => await _loginService.Login(Login, Password));

LoginCommand.Subscribe(OnLoginCompleted);} // of ctor

private void OnLoginCompleted(bool loginSuccessed){ }

34

Достоинства ReactiveCommand Не нужно мониторить значения свойств Login и PasswordНе нужно мониторить начало и конец асинхронной операции логина

35

Mugen: альтернативные XAML привязкиПримеры для TextBox.TextText Property, Mode=TwoWay, Validate=TrueText $string.Format('{0} {1}', Prop1, Prop2), Delay=100Text Property.MyCustomMethod()Text Prop1 ?? Prop2Text $CustomMethod(Prop1, Prop2, ‘string value’)Text Prop1 == ‘test’ ? Prop2 : ‘value’

36

Достоинства XAML привязок из Mugen:Поддержка синтаксиса C#Операторы ??, ?:, +, -, *, /, %, , ==, !=, <, >, <=, >=, &&(and), ||(or), |, &, !,

Ключевые слова $self – текущий элемент$root – корневой элемент$context – текущий DataContext$args – текущий параметр EventArgs

37

Недостаток Mugen привязокАльтернативная реализация Binding, которую нужно решиться использовать в продакшене

38

Итоги: навигацияMVVM нужен для навигацииНавигация ViewFirstАналог навигации в веб-приложенияхУдобна для WinRT, UWPРеализована в Prism

Навигация ViewModelFirstАналог навигации в настольных приложенияхУдобна для WPF, SilverlightРеализована в MugenMvvmToolkit, ReactiveUI

39

Несколько MVVM фреймворков для UWPНавигация – PrismКоманды – ReactiveUI Привязки ViewModel – ReactiveUI вместо MessageBus (EventAggregator)Привязки XAML – Mugen привязки вместо BindingPrism используется как MVVM фреймворк, Mugen и ReactiveUI – как библиотеки

40

Особенности использования нескольких MVVM

ДостоинствоСоединяем преимущества всех MVVM фреймворков

НедостатокВ рамках CodeReview нужно следить за тем, что каждый MVVM используется только для своей задачи

#msdevcon

Что дальше

Посмотреть сэмплы

ReactiveUI и Mugen

Начните с небольших

задачВыпилить

MessageBusReactiveUI – командыMugenMvvmToolkit –

привязки XAML

EventAggregator или Messenger заменить на

привязки уровня ViewModel

Вам понравится ))

#msdevcon

Полезные ресурсы

MugenMvvmToolkithttps://github.com/MugenMvvmToolkithttps://habrahabr.ru/post/236745/

ReactiveUIhttp://reactiveui.net/https://github.com/reactiveui

Как реализовать CompositeUI без MessageBushttps://github.com/denis-tsv/Prism.StoreApps.Extensions.Mvvm

#msdevcon

Q&AОбъять необъятное, или как использовать несколько MVVM фреймворков в одном XAML проектеДенис Цветцихden.tsvettsih@yandex.ru

© 2016 Microsoft Corporation. All rights reserved.

top related