Разделы презентаций


Разработка WPF приложений в стиле ViewModel First

Содержание

Почему это актуальноWPF все ещё жив MVVM – тема множества докладов и статей Множество разных реализацийот MVVM.Lightдо Prism с мануалом на 250 страниц

Слайды и текст этой презентации

Слайд 1Разработка WPF приложений в стиле ViewModel First
Денис Цветцих
АстроСофт
http://www.astrosoft.ru/
11-я конференция .NET

разработчиков
31 октября 2015
dotnetconf.ru

Разработка WPF приложений в стиле ViewModel FirstДенис ЦветцихАстроСофтhttp://www.astrosoft.ru/11-я конференция .NET разработчиков31 октября 2015dotnetconf.ru

Слайд 2Почему это актуально
WPF все ещё жив 
MVVM – тема множества

докладов и статей
Множество разных реализаций
от MVVM.Light
до Prism с мануалом

на 250 страниц

Почему это актуальноWPF все ещё жив MVVM – тема множества докладов и статей Множество разных реализацийот MVVM.Lightдо

Слайд 3В чем проблема?
Много разных реализаций MVVM
Непонятно, чем они отличаются
Непонятно, какую

из них использовать и в каких случаях

В чем проблема?Много разных реализаций MVVMНепонятно, чем они отличаютсяНепонятно, какую из них использовать и в каких случаях

Слайд 4Почему я здесь
Накоплен интересный опыт участия в WPF проектах
Есть опыт,

связанный с фреймворками:
Использование сторонних
Доработка сторонних
Изобретение своего MVVM фреймворка 


Почему я здесьНакоплен интересный опыт участия в WPF проектахЕсть опыт, связанный с фреймворками:Использование стороннихДоработка стороннихИзобретение своего MVVM

Слайд 5Опрос
Кто собирается написать WPF приложение?
Кто при этом использовал какие-нибудь

MVVM библиотеки/фреймворки?
Кто их вас изобрел свой собственный MVVM велосипед фреймворк?

Опрос Кто собирается написать WPF приложение?Кто при этом использовал какие-нибудь MVVM библиотеки/фреймворки?Кто их вас изобрел свой собственный

Слайд 6О чем мы поговорим?
Что такое MVVM?
Какими бывают подходы к его

реализации?
Как отличаются организация CompositeUI и дочерних окон в разных подходах?
Какой

подход лучше использовать?
Где найти реализацию этого подхода?
Рекомендации на основе нашего опыта
О чем мы поговорим?Что такое MVVM?Какими бывают подходы к его реализации?Как отличаются организация CompositeUI и дочерних окон

Слайд 7Model-View-ViewModel

Model-View-ViewModel

Слайд 8Что со всем этим делать?
Как решать типовые задачи?
CompositeUI (MasterDetail форма)
Навигация

(дочерние окна)

Что со всем этим делать?Как решать типовые задачи?CompositeUI (MasterDetail форма)Навигация (дочерние окна)

Слайд 9Нам нужен MVVM фреймворк!
Бывает 2 типов:
ViewFirst
ViewModelFirst


Это не разные

реализации паттерна MVVM
Это разные подходы к решению типовых задач

с использованием MVVM
Нам нужен MVVM фреймворк!Бывает 2 типов:ViewFirst ViewModelFirst Это не разные реализации паттерна MVVM Это разные подходы к

Слайд 10Composite ui

Composite ui

Слайд 11Master Detail

Master Detail

Слайд 12ViewFirst (Prism)
Отображение нового региона:
Создать View
Создать ViewModel для View
View.DataContext = ViewModel
Инициализировать

ViewModel

ViewFirst (Prism)Отображение нового региона:Создать ViewСоздать ViewModel для ViewView.DataContext = ViewModelИнициализировать ViewModel

Слайд 13MainWinow













MainWinow

Слайд 14UserListView




Grid.Row="1" x:Name="UserListBox"
SelectedItem="{Binding SelectedUser, Mode=TwoWay}"

ItemsSource="{Binding Users}">










public UserListView()
{
DataContext = new UserListViewModel();
}
UserListView

Слайд 15UserDetailsView




Text="{Binding User.FirstName}" />



public UserDetailsView()
{


DataContext = new UserDetailsViewModel();
}
UserDetailsView      public UserDetailsView(){    DataContext = new UserDetailsViewModel();}

Слайд 16UserListViewModel
public class UserListViewModel : ViewModel
{
private User _selectedUser;

public IEnumerable Users { get; } // инициализация

public

User SelectedUser
{
get { return _selectedUser; }
set
{
_selectedUser = value;
OnPropertyChanged();
}
}
}
UserListViewModelpublic class UserListViewModel : ViewModel{  private User _selectedUser;  public IEnumerable Users { get; } //

Слайд 17UserDetailsViewModel
public class UserDetailsViewModel : ViewModel
{
private User _user;

public

User User
{
get { return

_user; }
set
{
_user = value;
OnPropertyChanged();
}
}
}
UserDetailsViewModelpublic class UserDetailsViewModel : ViewModel{	 private User _user;  public User User  {

Слайд 18Вопрос
Как сделать так, чтобы UserListViewModel.SelectedUser синхронизировалось с UserDetailsViewModel.User?

Ответ в стиле

ViewFirst – MessageBus

Вопрос	Как сделать так, чтобы UserListViewModel.SelectedUser синхронизировалось с UserDetailsViewModel.User?Ответ в стиле ViewFirst – MessageBus

Слайд 19MessageBus

MessageBus

Слайд 20MessageBus
public class MessageBus
{
public static MessageBus Instance = new

MessageBus();

public event EventHandler SelectedUserChanged;

public void OnSelectedUserChanged(User

user)
{
SelectedUserChanged?.Invoke(this, new UserChangedEventArgs(user));
}
}

public class UserChangedEventArgs : EventArgs
{
public UserChangedEventArgs(User user)
{
User = user;
}
public User User { get; }
}

MessageBuspublic class MessageBus{  public static MessageBus Instance = new MessageBus();  public event EventHandler SelectedUserChanged;

Слайд 21UserListViewModel
public class UserListViewModel : ViewModel
{
public User SelectedUser

{
get { return _selectedUser; }

set
{
_selectedUser = value;
OnPropertyChanged();

MessageBus.Instance.OnSelectedUserChanged(value);
}
}
}
UserListViewModel public class UserListViewModel : ViewModel{  public User SelectedUser  {    get {

Слайд 22UserDetailsViewModel
public class UserDetailsViewModel : ViewModel
{
public UserDetailsViewModel()

{
MessageBus.Instance.SelectedUserChanged +=
(s, e) => User

= e.User;
}
}
UserDetailsViewModel public class UserDetailsViewModel : ViewModel{  public UserDetailsViewModel()  {    MessageBus.Instance.SelectedUserChanged += 			(s,

Слайд 23Недостатки
1) Используется MessageBus, предназначенный для интеграции систем
2) На широковещательное

событие может подписаться любой объект
3) Поведение системы становится запутанным и

неочевидным

Недостатки 1) Используется MessageBus, предназначенный для интеграции систем2) На широковещательное событие может подписаться любой объект3) Поведение системы

Слайд 24ViewModelFirst (энтузиасты)
Отображение нового региона:
1) Создать ViewModel
2) Инициализировать ViewModel
3) Создать View

для ViewModel
4) View.DataContext = ViewModel

ViewModelFirst (энтузиасты)Отображение нового региона:1) Создать ViewModel2) Инициализировать ViewModel3) Создать View для ViewModel4) View.DataContext = ViewModel

Слайд 25Чистим CodeBehind
public UserListView()
{
DataContext = new UserListViewModel();
}
public

UserDetailsView()
{
DataContext = new UserDetailsViewModel();
}


Чистим CodeBehindpublic UserListView(){    DataContext = new UserListViewModel();}public UserDetailsView(){    DataContext = new

Слайд 26Убираем MessageBus
public class UserListViewModel : ViewModel
{
public User SelectedUser

{
get { return _selectedUser; }

set
{
_selectedUser = value;
OnPropertyChanged();

MessageBus.Instance.OnSelectedUserChanged(value);
}
}
}




Убираем MessageBuspublic class UserListViewModel : ViewModel{  public User SelectedUser  {    get {

Слайд 27Убираем MessageBus
public class UserDetailsViewModel : ViewModel
{
public UserDetailsViewModel()

{
MessageBus.Instance.SelectedUserChanged +=
(s, e) => User

= e.User;
}
}
Убираем MessageBuspublic class UserDetailsViewModel : ViewModel{  public UserDetailsViewModel()  {    MessageBus.Instance.SelectedUserChanged += 			(s,

Слайд 28Вопрос
Как сделать так, чтобы UserListViewModel.SelectedUser синхронизировалось с UserDetailsViewModel.User?

Ответ в стиле

ViewModelFirst – нам нужна родительская ViewModel

Вопрос	Как сделать так, чтобы UserListViewModel.SelectedUser синхронизировалось с UserDetailsViewModel.User?Ответ в стиле ViewModelFirst – нам нужна родительская ViewModel

Слайд 29MainWindowViewModel
public class MainWindowViewModel : ViewModel
{
public UserDetailsViewModel UserDetailsViewModel {

get; private set; }
public UserListViewModel UserListViewModel { get;

private set; }

public void Initialize()
{
UserListViewModel.PropertyChanged += (s, e) =>
{
if (e.PropertyName == "SelectedUser")
UserDetailsViewModel.User = UserListViewModel.SelectedUser;
};
}
}
MainWindowViewModelpublic class MainWindowViewModel : ViewModel{  public UserDetailsViewModel UserDetailsViewModel { get; private set; }  public UserListViewModel

Слайд 30MainWindow






DataContext="{Binding UserListViewModel}"
Grid.Column="0" />

DataContext="{Binding UserDetailsViewModel}"
Grid.Column="1" />

MainWindow

Слайд 31ViewFirst vs ViewModelFirst

ViewFirst vs ViewModelFirst

Слайд 32Навигация

Навигация

Слайд 33ViewFirst: показать новый элемент
Дочернее окно, новый таб:

Navigation.Show(Value);
или
Navigation.Show("View", Value);


Аналогично вебу: http://address.ru/?arg=value

ViewFirst

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

ViewFirst: показать новый элементДочернее окно, новый таб:Navigation.Show(Value);илиNavigation.Show(

Слайд 34ViewModelFirst: показать новый элемент
var vm = Navigation.Get();
vm.Arg = Value;
vm.Show();

Аналогично окну

WPF:
var wnd = new Window();
wnd.Arg1 = Value1;
wnd.Show();

ViewModelFirst: показать новый элементvar vm = Navigation.Get();vm.Arg = Value;vm.Show();Аналогично окну WPF:var wnd = new Window();wnd.Arg1 = Value1;wnd.Show();

Слайд 35ViewFirst vs ViewModelFirst

ViewFirst vs ViewModelFirst

Слайд 36Дочернее окно

Дочернее окно

Слайд 37Отображение дочернего окна
private void OnShowDetails(User user)
{
var detailsVM =


Factory.Resolve();

detailsVM.User = user;
detailsVM.Closed +=

(s, e) => { /* обработка e.DialogResult */ };

detailsVM.Show();
}

Отображение дочернего окнаprivate void OnShowDetails(User user){  var detailsVM = 		Factory.Resolve();  detailsVM.User = user;  detailsVM.Closed

Слайд 38ChildViewModel
public abstract class ChildViewModel : ViewModel, IChildViewModel
{
[Dependency]

public IChildViewModelManager ChildViewModelManager { private get; set; }

public

bool IsClosed { get; private set; } // уже закрыли или нет?

protected void Close()
{
if (IsClosed) throw new InvalidOperationException(“closed");

IsClosed = true;

ChildViewModelManager.Close(this);
}

public void Show()
{
ChildViewModelManager.Show(this);
}
}
ChildViewModelpublic abstract class ChildViewModel : ViewModel, IChildViewModel{  [Dependency]  public IChildViewModelManager ChildViewModelManager { private get; set;

Слайд 39ChildViewModelManager
public class ChildViewModelManager : IChildViewModelManager
{
// открытые окна
private

readonly Dictionary _openedWindows
= new Dictionary();

//

по типу ViewModel возвращает View
[Dependency]
public IViewTypeResolver ViewTypeResolver
{ private get; set; }

}
ChildViewModelManagerpublic class ChildViewModelManager : IChildViewModelManager{	 // открытые окна  private readonly Dictionary _openedWindows 		= new Dictionary();

Слайд 40ChildViewModelManager: Show
private void Show(IChildViewModel viewModel)
{
// получить тип окна,

которое будем открывать
var windowType = ViewTypeResolver.
ResolveViewType(viewModel.GetType());

// создать экземпляр

окна
var window =
(Window)Activator.CreateInstance(windowType);

// запомнить, какое окно открываем
_openedWindows.Add(viewModel.GetType(), window);

window.DataContext = viewModel;

// показать окно
window.Show();
}

ChildViewModelManager: Showprivate void Show(IChildViewModel viewModel){  // получить тип окна, которое будем открывать  var windowType =

Слайд 41ChildViewModelManager: Close
public void Close(IChildViewModel viewModel)
{
// какое окно закрываем

var window = _openedWindows[viewModel.GetType()];

// убираем из

списка открытых
_openedWindows.Remove(viewModel.GetType());

// закрываем
Application.Current.Dispatcher.BeginInvoke(
new Action(() => window.Close()), null);
}
ChildViewModelManager: Closepublic void Close(IChildViewModel viewModel){ 	 // какое окно закрываем  var window = _openedWindows[viewModel.GetType()];

Слайд 42ChildWindow
public abstract class ChildWindow : Window
{
protected override void

OnClosing(CancelEventArgs e)
{
base.OnClosing(e);

var viewModel = (ChildViewModel)DataContext;

// если ViewModel на находится в состоянии «Закрыто»
if (!viewModel.IsClosed)
{
e.Cancel = true; // не закрываем окно

// запрашиваем изменение состояния ViewModel
viewModel.Close();
}
}
}
ChildWindowpublic abstract class ChildWindow : Window{  protected override void OnClosing(CancelEventArgs e)  {

Слайд 43Особенности ViewModelFirst
Достоинства
Позволяет реализовать CompositeUI
Не требует реализации MessageBus
Взаимодействие ViewModel более очевидное
Нет

MessageBus – нет его использования не по назначению
Позволяет удобно реализовать

поддержку дочерних окон
Недостатки
Не имеет вендорской поддержки
Особенности ViewModelFirstДостоинстваПозволяет реализовать CompositeUIНе требует реализации MessageBusВзаимодействие ViewModel более очевидноеНет MessageBus – нет его использования не по

Слайд 44Наш рецепт
ViewModelFirst
Свой велосипед
Mugen MVVM Toolkit
IoC контейнер
ReactiveUI (ограничено)
ReactiveCommand
ObservableForProperty
Отдельная сборка для

ViewModel


Наш рецептViewModelFirst Свой велосипедMugen MVVM ToolkitIoC контейнерReactiveUI (ограничено)ReactiveCommandObservableForPropertyОтдельная сборка для ViewModel

Слайд 45Материалы по ViewModelFirst
Материалы доклада на GitHub:
https://github.com/denis-tsv/ViewFirst-vs-ViewModelFirst

Курс «Методология синхронной разработки приложений

в Microsoft Visual Studio 2010»
www.intuit.ru/studies/courses/2322/622/info

Mugen MVVM Toolkit
http://habrahabr.ru/post/236745/

Материалы по ViewModelFirstМатериалы доклада на GitHub:https://github.com/denis-tsv/ViewFirst-vs-ViewModelFirstКурс «Методология синхронной разработки приложений в Microsoft Visual Studio 2010»www.intuit.ru/studies/courses/2322/622/infoMugen MVVM Toolkithttp://habrahabr.ru/post/236745/

Слайд 46Спасибо за внимание
Денис Цветцих
АстроСофт
den.tsvettsih@yandex.ru

Спасибо за вниманиеДенис ЦветцихАстроСофтden.tsvettsih@yandex.ru

Обратная связь

Если не удалось найти и скачать доклад-презентацию, Вы можете заказать его на нашем сайте. Мы постараемся найти нужный Вам материал и отправим по электронной почте. Не стесняйтесь обращаться к нам, если у вас возникли вопросы или пожелания:

Email: Нажмите что бы посмотреть 

Что такое TheSlide.ru?

Это сайт презентации, докладов, проектов в PowerPoint. Здесь удобно  хранить и делиться своими презентациями с другими пользователями.


Для правообладателей

Яндекс.Метрика