SlideShare ist ein Scribd-Unternehmen logo
1 von 46
Разработка WPF приложений
в стиле ViewModel First
Денис Цветцих
АстроСофт
http://www.astrosoft.ru/
11-я конференция .NET разработчиков
31 октября 2015
dotnetconf.ru
2
Почему это актуально
• WPF все ещё жив 
• MVVM – тема множества докладов и статей
• Множество разных реализаций
• от MVVM.Light
• до Prism с мануалом на 250 страниц
3
В чем проблема?
Много разных реализаций MVVM
• Непонятно, чем они отличаются
• Непонятно, какую из них использовать и
в каких случаях
4
Почему я здесь
• Накоплен интересный опыт участия в WPF
проектах
• Есть опыт, связанный с фреймворками:
• Использование сторонних
• Доработка сторонних
• Изобретение своего MVVM фреймворка 
5
Опрос
• Кто собирается написать WPF приложение?
• Кто при этом использовал какие-нибудь
MVVM библиотеки/фреймворки?
• Кто их вас изобрел свой собственный
MVVM велосипед фреймворк?
6
О чем мы поговорим?
• Что такое MVVM?
• Какими бывают подходы к его реализации?
• Как отличаются организация CompositeUI и
дочерних окон в разных подходах?
• Какой подход лучше использовать?
• Где найти реализацию этого подхода?
• Рекомендации на основе нашего опыта
7
Model-View-ViewModel
8
Что со всем этим делать?
Как решать типовые задачи?
• CompositeUI (MasterDetail форма)
• Навигация (дочерние окна)
9
Нам нужен MVVM фреймворк!
Бывает 2 типов:
• ViewFirst
• ViewModelFirst
Это не разные реализации паттерна MVVM
Это разные подходы к решению типовых задач с
использованием MVVM
COMPOSITE UI
11
Master Detail
12
ViewFirst (Prism)
Отображение нового региона:
1) Создать View
2) Создать ViewModel для View
3) View.DataContext = ViewModel
4) Инициализировать ViewModel
13
MainWinow
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<view:UserListView Grid.Column="0" />
<view:UserDetailsView Grid.Column="1" />
</Grid>
14
UserListView
<Grid>
<TextBlock Grid.Row="0" Text="User list" FontWeight="Bold" />
<ListBox Grid.Row="1" x:Name="UserListBox"
SelectedItem="{Binding SelectedUser, Mode=TwoWay}"
ItemsSource="{Binding Users}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding FirstName}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
public UserListView()
{
DataContext = new UserListViewModel();
}
15
UserDetailsView
<StackPanel Orientation="Vertical">
<TextBlock Text="User details" FontWeight="Bold" />
<TextBlock Text="{Binding User.FirstName}" />
<TextBlock Text="{Binding User.LastName}" />
</StackPanel>
public UserDetailsView()
{
DataContext = new UserDetailsViewModel();
}
16
UserListViewModel
public class UserListViewModel : ViewModel
{
private User _selectedUser;
public IEnumerable<User> Users { get; } // инициализация
public User SelectedUser
{
get { return _selectedUser; }
set
{
_selectedUser = value;
OnPropertyChanged();
}
}
}
17
UserDetailsViewModel
public class UserDetailsViewModel : ViewModel
{
private User _user;
public User User
{
get { return _user; }
set
{
_user = value;
OnPropertyChanged();
}
}
}
18
Вопрос
Как сделать так, чтобы
UserListViewModel.SelectedUser
синхронизировалось с
UserDetailsViewModel.User?
Ответ в стиле ViewFirst – MessageBus
19
MessageBus
20
MessageBus
public class MessageBus
{
public static MessageBus Instance = new MessageBus();
public event EventHandler<UserChangedEventArgs> 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; }
}
21
UserListViewModel
public class UserListViewModel : ViewModel
{
public User SelectedUser
{
get { return _selectedUser; }
set
{
_selectedUser = value;
OnPropertyChanged();
MessageBus.Instance.OnSelectedUserChanged(value);
}
}
}
22
UserDetailsViewModel
public class UserDetailsViewModel : ViewModel
{
public UserDetailsViewModel()
{
MessageBus.Instance.SelectedUserChanged +=
(s, e) => User = e.User;
}
}
23
Недостатки
1) Используется MessageBus,
предназначенный для интеграции систем
2) На широковещательное событие может
подписаться любой объект
3) Поведение системы становится
запутанным и неочевидным
24
ViewModelFirst (энтузиасты)
Отображение нового региона:
1) Создать ViewModel
2) Инициализировать ViewModel
3) Создать View для ViewModel
4) View.DataContext = ViewModel
25
Чистим CodeBehind
public UserListView()
{
DataContext = new UserListViewModel();
}
public UserDetailsView()
{
DataContext = new UserDetailsViewModel();
}
26
Убираем MessageBus
public class UserListViewModel : ViewModel
{
public User SelectedUser
{
get { return _selectedUser; }
set
{
_selectedUser = value;
OnPropertyChanged();
MessageBus.Instance.OnSelectedUserChanged(value);
}
}
}
27
Убираем MessageBus
public class UserDetailsViewModel : ViewModel
{
public UserDetailsViewModel()
{
MessageBus.Instance.SelectedUserChanged +=
(s, e) => User = e.User;
}
}
28
Вопрос
Как сделать так, чтобы
UserListViewModel.SelectedUser
синхронизировалось с
UserDetailsViewModel.User?
Ответ в стиле ViewModelFirst – нам нужна
родительская ViewModel
29
MainWindowViewModel
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;
};
}
}
30
MainWindow
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<views:UserListView
DataContext="{Binding UserListViewModel}"
Grid.Column="0" />
<views:UserDetailsView
DataContext="{Binding UserDetailsViewModel}"
Grid.Column="1" />
</Grid>
31
ViewFirst vs ViewModelFirst
ViewFirst ViewModelFitst
CompositeUI да да
Взаимодействие
ViewModel
MessageBus Родетельская
ViewModel
НАВИГАЦИЯ
33
ViewFirst: показать новый элемент
Дочернее окно, новый таб:
Navigation.Show<ViewModel>(Value);
или
Navigation.Show("View", Value);
Аналогично вебу: http://address.ru/?arg=value
ViewFirst предлагает в WPF организовать навигацию
аналогично веб-приложению
34
ViewModelFirst: показать новый элемент
var vm = Navigation.Get<ViewModel>();
vm.Arg = Value;
vm.Show();
Аналогично окну WPF:
var wnd = new Window();
wnd.Arg1 = Value1;
wnd.Show();
35
ViewFirst vs ViewModelFirst
ViewFirst ViewModelFirst
Создать View Создать ViewModel
Создать ViewModel Инициализировать ViewModel
Инициализировать ViewModel Создать View
View.DataContext = ViewModel View.DataContext = ViewModel
36
Дочернее окно
37
Отображение дочернего окна
private void OnShowDetails(User user)
{
var detailsVM =
Factory.Resolve<UserDetailsWindowViewModel>();
detailsVM.User = user;
detailsVM.Closed +=
(s, e) => { /* обработка e.DialogResult */ };
detailsVM.Show();
}
38
ChildViewModel
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);
}
}
39
ChildViewModelManager
public class ChildViewModelManager : IChildViewModelManager
{
// открытые окна
private readonly Dictionary<Type, Window> _openedWindows
= new Dictionary<Type, Window>();
// по типу ViewModel возвращает View
[Dependency]
public IViewTypeResolver ViewTypeResolver
{ private get; set; }
}
40
ChildViewModelManager: 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();
}
41
ChildViewModelManager: Close
public void Close(IChildViewModel viewModel)
{
// какое окно закрываем
var window = _openedWindows[viewModel.GetType()];
// убираем из списка открытых
_openedWindows.Remove(viewModel.GetType());
// закрываем
Application.Current.Dispatcher.BeginInvoke(
new Action(() => window.Close()), null);
}
42
ChildWindow
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();
}
}
}
43
Особенности ViewModelFirst
Достоинства
• Позволяет реализовать CompositeUI
• Не требует реализации MessageBus
• Взаимодействие ViewModel более очевидное
• Нет MessageBus – нет его использования не
по назначению
• Позволяет удобно реализовать
поддержку дочерних окон
Недостатки
• Не имеет вендорской поддержки
44
Наш рецепт
• ViewModelFirst
• Свой велосипед
• Mugen MVVM Toolkit
• IoC контейнер
• ReactiveUI (ограничено)
• ReactiveCommand
• ObservableForProperty
• Отдельная сборка для 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/
46
Спасибо за внимание
Денис Цветцих
АстроСофт
den.tsvettsih@yandex.ru

Weitere ähnliche Inhalte

Was ist angesagt?

«Как я научился не волноваться и полюбил Android-MVP», Никита Бартишок, ABBYY
«Как я научился не волноваться и полюбил Android-MVP», Никита Бартишок, ABBYY«Как я научился не волноваться и полюбил Android-MVP», Никита Бартишок, ABBYY
«Как я научился не волноваться и полюбил Android-MVP», Никита Бартишок, ABBYYMail.ru Group
 
Moxy. Из чего состоит и как этим пользоваться
Moxy. Из чего состоит и как этим пользоватьсяMoxy. Из чего состоит и как этим пользоваться
Moxy. Из чего состоит и как этим пользоватьсяYuri Shmakov
 
Windows Azure and node js
Windows Azure and node jsWindows Azure and node js
Windows Azure and node jsAlex Tumanoff
 
HTML 5: будущее уже сегодня, Сергей Байдачный, Microsoft Ukraine
HTML 5: будущее уже сегодня, Сергей Байдачный, Microsoft UkraineHTML 5: будущее уже сегодня, Сергей Байдачный, Microsoft Ukraine
HTML 5: будущее уже сегодня, Сергей Байдачный, Microsoft UkraineVolha Banadyseva
 
Dependency Injection на примере Unity и NInject
Dependency Injection на примере Unity и NInjectDependency Injection на примере Unity и NInject
Dependency Injection на примере Unity и NInjectakrakovetsky
 
«Buzzwords everywhere, или Борьба с ветряными мельницами», Артём Дроздов, Mai...
«Buzzwords everywhere, или Борьба с ветряными мельницами», Артём Дроздов, Mai...«Buzzwords everywhere, или Борьба с ветряными мельницами», Артём Дроздов, Mai...
«Buzzwords everywhere, или Борьба с ветряными мельницами», Артём Дроздов, Mai...Mail.ru Group
 
CodeFest 2011. Крестьянинов М. — Обзор аспектно-ориентированного программиров...
CodeFest 2011. Крестьянинов М. — Обзор аспектно-ориентированного программиров...CodeFest 2011. Крестьянинов М. — Обзор аспектно-ориентированного программиров...
CodeFest 2011. Крестьянинов М. — Обзор аспектно-ориентированного программиров...CodeFest
 
Vue.js и его брат-близнец Vue-server.js / Андрей Солодовников (НГС)
Vue.js и его брат-близнец Vue-server.js / Андрей Солодовников (НГС)Vue.js и его брат-близнец Vue-server.js / Андрей Солодовников (НГС)
Vue.js и его брат-близнец Vue-server.js / Андрей Солодовников (НГС)Ontico
 
занятие 2
занятие 2занятие 2
занятие 2ajantis
 
55+1 прием для улучшения Javascript-кода / Татьяна Бабич (Simbirsoft)
55+1 прием для улучшения Javascript-кода / Татьяна Бабич (Simbirsoft)55+1 прием для улучшения Javascript-кода / Татьяна Бабич (Simbirsoft)
55+1 прием для улучшения Javascript-кода / Татьяна Бабич (Simbirsoft)Ontico
 
JavaScript Базовый. Занятие 09.
JavaScript Базовый. Занятие 09.JavaScript Базовый. Занятие 09.
JavaScript Базовый. Занятие 09.Igor Shkulipa
 
МРТ для данных, Frontend Conf 2016
МРТ для данных, Frontend Conf 2016МРТ для данных, Frontend Conf 2016
МРТ для данных, Frontend Conf 2016Anastasia Goryacheva
 
Enterprise flex pure mvc, slides, russian
Enterprise flex pure mvc, slides, russianEnterprise flex pure mvc, slides, russian
Enterprise flex pure mvc, slides, russianSergiy Shychynov
 
Лекция Android. Fragments, ActionBar, Drawer
Лекция Android. Fragments, ActionBar, DrawerЛекция Android. Fragments, ActionBar, Drawer
Лекция Android. Fragments, ActionBar, DrawerАлександр Брич
 
Радости и гадости регрессионного тестирования вёрстки / Алексей Малейков (HTM...
Радости и гадости регрессионного тестирования вёрстки / Алексей Малейков (HTM...Радости и гадости регрессионного тестирования вёрстки / Алексей Малейков (HTM...
Радости и гадости регрессионного тестирования вёрстки / Алексей Малейков (HTM...Ontico
 
Fragments (Lecture 09 – Fragments)
Fragments (Lecture 09 – Fragments)Fragments (Lecture 09 – Fragments)
Fragments (Lecture 09 – Fragments)Noveo
 
Школа-студия разработки приложений для iOS. 2 лекция. MVC, View, Controllers
Школа-студия разработки приложений для iOS. 2 лекция. MVC, View, ControllersШкола-студия разработки приложений для iOS. 2 лекция. MVC, View, Controllers
Школа-студия разработки приложений для iOS. 2 лекция. MVC, View, ControllersГлеб Тарасов
 

Was ist angesagt? (20)

«Как я научился не волноваться и полюбил Android-MVP», Никита Бартишок, ABBYY
«Как я научился не волноваться и полюбил Android-MVP», Никита Бартишок, ABBYY«Как я научился не волноваться и полюбил Android-MVP», Никита Бартишок, ABBYY
«Как я научился не волноваться и полюбил Android-MVP», Никита Бартишок, ABBYY
 
Moxy. Из чего состоит и как этим пользоваться
Moxy. Из чего состоит и как этим пользоватьсяMoxy. Из чего состоит и как этим пользоваться
Moxy. Из чего состоит и как этим пользоваться
 
Gwt jug basic
Gwt jug basicGwt jug basic
Gwt jug basic
 
Windows Azure and node js
Windows Azure and node jsWindows Azure and node js
Windows Azure and node js
 
HTML 5: будущее уже сегодня, Сергей Байдачный, Microsoft Ukraine
HTML 5: будущее уже сегодня, Сергей Байдачный, Microsoft UkraineHTML 5: будущее уже сегодня, Сергей Байдачный, Microsoft Ukraine
HTML 5: будущее уже сегодня, Сергей Байдачный, Microsoft Ukraine
 
Dependency Injection на примере Unity и NInject
Dependency Injection на примере Unity и NInjectDependency Injection на примере Unity и NInject
Dependency Injection на примере Unity и NInject
 
«Buzzwords everywhere, или Борьба с ветряными мельницами», Артём Дроздов, Mai...
«Buzzwords everywhere, или Борьба с ветряными мельницами», Артём Дроздов, Mai...«Buzzwords everywhere, или Борьба с ветряными мельницами», Артём Дроздов, Mai...
«Buzzwords everywhere, или Борьба с ветряными мельницами», Артём Дроздов, Mai...
 
CodeFest 2011. Крестьянинов М. — Обзор аспектно-ориентированного программиров...
CodeFest 2011. Крестьянинов М. — Обзор аспектно-ориентированного программиров...CodeFest 2011. Крестьянинов М. — Обзор аспектно-ориентированного программиров...
CodeFest 2011. Крестьянинов М. — Обзор аспектно-ориентированного программиров...
 
Vue.js и его брат-близнец Vue-server.js / Андрей Солодовников (НГС)
Vue.js и его брат-близнец Vue-server.js / Андрей Солодовников (НГС)Vue.js и его брат-близнец Vue-server.js / Андрей Солодовников (НГС)
Vue.js и его брат-близнец Vue-server.js / Андрей Солодовников (НГС)
 
занятие 2
занятие 2занятие 2
занятие 2
 
55+1 прием для улучшения Javascript-кода / Татьяна Бабич (Simbirsoft)
55+1 прием для улучшения Javascript-кода / Татьяна Бабич (Simbirsoft)55+1 прием для улучшения Javascript-кода / Татьяна Бабич (Simbirsoft)
55+1 прием для улучшения Javascript-кода / Татьяна Бабич (Simbirsoft)
 
JavaScript Базовый. Занятие 09.
JavaScript Базовый. Занятие 09.JavaScript Базовый. Занятие 09.
JavaScript Базовый. Занятие 09.
 
МРТ для данных, Frontend Conf 2016
МРТ для данных, Frontend Conf 2016МРТ для данных, Frontend Conf 2016
МРТ для данных, Frontend Conf 2016
 
Enterprise flex pure mvc, slides, russian
Enterprise flex pure mvc, slides, russianEnterprise flex pure mvc, slides, russian
Enterprise flex pure mvc, slides, russian
 
Лекция 2. Activity.
Лекция 2. Activity.Лекция 2. Activity.
Лекция 2. Activity.
 
Лекция Android. Fragments, ActionBar, Drawer
Лекция Android. Fragments, ActionBar, DrawerЛекция Android. Fragments, ActionBar, Drawer
Лекция Android. Fragments, ActionBar, Drawer
 
Радости и гадости регрессионного тестирования вёрстки / Алексей Малейков (HTM...
Радости и гадости регрессионного тестирования вёрстки / Алексей Малейков (HTM...Радости и гадости регрессионного тестирования вёрстки / Алексей Малейков (HTM...
Радости и гадости регрессионного тестирования вёрстки / Алексей Малейков (HTM...
 
Fragments (Lecture 09 – Fragments)
Fragments (Lecture 09 – Fragments)Fragments (Lecture 09 – Fragments)
Fragments (Lecture 09 – Fragments)
 
Fragments, ActionBar, Drawer
Fragments, ActionBar, DrawerFragments, ActionBar, Drawer
Fragments, ActionBar, Drawer
 
Школа-студия разработки приложений для iOS. 2 лекция. MVC, View, Controllers
Школа-студия разработки приложений для iOS. 2 лекция. MVC, View, ControllersШкола-студия разработки приложений для iOS. 2 лекция. MVC, View, Controllers
Школа-студия разработки приложений для iOS. 2 лекция. MVC, View, Controllers
 

Andere mochten auch

Разработка Windows 8 приложений глазами WPF/Silverlight программиста
Разработка Windows 8 приложений глазами WPF/Silverlight программистаРазработка Windows 8 приложений глазами WPF/Silverlight программиста
Разработка Windows 8 приложений глазами WPF/Silverlight программистаDenis Tsvettsih
 
Roslyn API : SyntaxTree vs CodeDom, SemanticModel vs Reflection
Roslyn API: SyntaxTree vs CodeDom, SemanticModel vs ReflectionRoslyn API: SyntaxTree vs CodeDom, SemanticModel vs Reflection
Roslyn API : SyntaxTree vs CodeDom, SemanticModel vs ReflectionDenis Tsvettsih
 
Эффективные email коммуникации
Эффективные email коммуникацииЭффективные email коммуникации
Эффективные email коммуникацииDenis Tsvettsih
 
Situacion problematica
Situacion problematicaSituacion problematica
Situacion problematicaanalauramarzo3
 
Gutell 098.jmb.2006.360.0978
Gutell 098.jmb.2006.360.0978Gutell 098.jmb.2006.360.0978
Gutell 098.jmb.2006.360.0978Robin Gutell
 
Pa gastom
Pa gastomPa gastom
Pa gastomda_lia
 
Presentación2
Presentación2Presentación2
Presentación2Aneluzh
 
Mapa conceptual. Conservación del Ambiente
Mapa conceptual. Conservación del  Ambiente Mapa conceptual. Conservación del  Ambiente
Mapa conceptual. Conservación del Ambiente Hellen Benedetti
 
GOLIN / DIGITAL & SOCIAL MEDIA EXCELLENCE / HONG KONG
GOLIN / DIGITAL & SOCIAL MEDIA EXCELLENCE / HONG KONGGOLIN / DIGITAL & SOCIAL MEDIA EXCELLENCE / HONG KONG
GOLIN / DIGITAL & SOCIAL MEDIA EXCELLENCE / HONG KONGZaheer Nooruddin
 
HREFLANG for International SEO: Lessons from 3,000 Implementations
HREFLANG for International SEO: Lessons from 3,000 ImplementationsHREFLANG for International SEO: Lessons from 3,000 Implementations
HREFLANG for International SEO: Lessons from 3,000 ImplementationsErudite
 
深層強化学習 Pydata.Okinawa Meetup #22
深層強化学習 Pydata.Okinawa Meetup #22深層強化学習 Pydata.Okinawa Meetup #22
深層強化学習 Pydata.Okinawa Meetup #22Naoto Yoshida
 
El conocimiento 3ro bach c kevin alvear
El conocimiento 3ro bach c kevin alvearEl conocimiento 3ro bach c kevin alvear
El conocimiento 3ro bach c kevin alvearKevin Alvear Carrion
 
Mi contexto de formacion
Mi contexto de formacionMi contexto de formacion
Mi contexto de formacionYomaris Castro
 
Herramientas Digitales
Herramientas DigitalesHerramientas Digitales
Herramientas DigitalesJames Romero
 
Maria de -freitas -chamilo
Maria  de -freitas -chamiloMaria  de -freitas -chamilo
Maria de -freitas -chamilomaria20139
 

Andere mochten auch (19)

MVVM in WPF
MVVM in WPFMVVM in WPF
MVVM in WPF
 
Разработка Windows 8 приложений глазами WPF/Silverlight программиста
Разработка Windows 8 приложений глазами WPF/Silverlight программистаРазработка Windows 8 приложений глазами WPF/Silverlight программиста
Разработка Windows 8 приложений глазами WPF/Silverlight программиста
 
Roslyn API : SyntaxTree vs CodeDom, SemanticModel vs Reflection
Roslyn API: SyntaxTree vs CodeDom, SemanticModel vs ReflectionRoslyn API: SyntaxTree vs CodeDom, SemanticModel vs Reflection
Roslyn API : SyntaxTree vs CodeDom, SemanticModel vs Reflection
 
Эффективные email коммуникации
Эффективные email коммуникацииЭффективные email коммуникации
Эффективные email коммуникации
 
Situacion problematica
Situacion problematicaSituacion problematica
Situacion problematica
 
Presentación1
Presentación1Presentación1
Presentación1
 
English day
English dayEnglish day
English day
 
Gutell 098.jmb.2006.360.0978
Gutell 098.jmb.2006.360.0978Gutell 098.jmb.2006.360.0978
Gutell 098.jmb.2006.360.0978
 
Pa gastom
Pa gastomPa gastom
Pa gastom
 
Presentación2
Presentación2Presentación2
Presentación2
 
Mapa conceptual. Conservación del Ambiente
Mapa conceptual. Conservación del  Ambiente Mapa conceptual. Conservación del  Ambiente
Mapa conceptual. Conservación del Ambiente
 
GOLIN / DIGITAL & SOCIAL MEDIA EXCELLENCE / HONG KONG
GOLIN / DIGITAL & SOCIAL MEDIA EXCELLENCE / HONG KONGGOLIN / DIGITAL & SOCIAL MEDIA EXCELLENCE / HONG KONG
GOLIN / DIGITAL & SOCIAL MEDIA EXCELLENCE / HONG KONG
 
HREFLANG for International SEO: Lessons from 3,000 Implementations
HREFLANG for International SEO: Lessons from 3,000 ImplementationsHREFLANG for International SEO: Lessons from 3,000 Implementations
HREFLANG for International SEO: Lessons from 3,000 Implementations
 
El domicilio.
El domicilio.El domicilio.
El domicilio.
 
深層強化学習 Pydata.Okinawa Meetup #22
深層強化学習 Pydata.Okinawa Meetup #22深層強化学習 Pydata.Okinawa Meetup #22
深層強化学習 Pydata.Okinawa Meetup #22
 
El conocimiento 3ro bach c kevin alvear
El conocimiento 3ro bach c kevin alvearEl conocimiento 3ro bach c kevin alvear
El conocimiento 3ro bach c kevin alvear
 
Mi contexto de formacion
Mi contexto de formacionMi contexto de formacion
Mi contexto de formacion
 
Herramientas Digitales
Herramientas DigitalesHerramientas Digitales
Herramientas Digitales
 
Maria de -freitas -chamilo
Maria  de -freitas -chamiloMaria  de -freitas -chamilo
Maria de -freitas -chamilo
 

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

MVVM в WinForms – DevExpress Way (теория и практика)
MVVM в WinForms – DevExpress Way (теория и практика)MVVM в WinForms – DevExpress Way (теория и практика)
MVVM в WinForms – DevExpress Way (теория и практика)GoSharp
 
Viper - чистая архитектура iOS-приложения (И. Чирков)
Viper - чистая архитектура iOS-приложения (И. Чирков)Viper - чистая архитектура iOS-приложения (И. Чирков)
Viper - чистая архитектура iOS-приложения (И. Чирков)65apps
 
Антон Валюх - Использование паттерна Mvvm в android
Антон Валюх - Использование паттерна Mvvm в androidАнтон Валюх - Использование паттерна Mvvm в android
Антон Валюх - Использование паттерна Mvvm в androidDataArt
 
Курсы по мобильной разработке. 2 лекция. Построение интерфейсов в iOS
Курсы по мобильной разработке. 2 лекция. Построение интерфейсов в iOSКурсы по мобильной разработке. 2 лекция. Построение интерфейсов в iOS
Курсы по мобильной разработке. 2 лекция. Построение интерфейсов в iOSГлеб Тарасов
 
AndroidMVPHelper
AndroidMVPHelperAndroidMVPHelper
AndroidMVPHelperDataArt
 
C# Web. Занятие 11.
C# Web. Занятие 11.C# Web. Занятие 11.
C# Web. Занятие 11.Igor Shkulipa
 
#MBLTdev: Опыт использования MVVM в реальных проектах
#MBLTdev: Опыт использования MVVM в реальных проектах#MBLTdev: Опыт использования MVVM в реальных проектах
#MBLTdev: Опыт использования MVVM в реальных проектахe-Legion
 
Веселая ферма. Соседи.
Веселая ферма. Соседи.Веселая ферма. Соседи.
Веселая ферма. Соседи.Doomer Samoiloff
 
Школа-Студия разработки приложений для iOS. 5 лекция. Разное
Школа-Студия разработки приложений для iOS. 5 лекция. РазноеШкола-Студия разработки приложений для iOS. 5 лекция. Разное
Школа-Студия разработки приложений для iOS. 5 лекция. РазноеГлеб Тарасов
 
'The best practices' by KONSTANTIN KULAKSYZ at OdessaJS'2020
'The best practices' by KONSTANTIN KULAKSYZ at OdessaJS'2020'The best practices' by KONSTANTIN KULAKSYZ at OdessaJS'2020
'The best practices' by KONSTANTIN KULAKSYZ at OdessaJS'2020OdessaJS Conf
 
#3 "Webpack и Vue.JS: Создание больших приложений и их расширение" Кирилл Кай...
#3 "Webpack и Vue.JS: Создание больших приложений и их расширение" Кирилл Кай...#3 "Webpack и Vue.JS: Создание больших приложений и их расширение" Кирилл Кай...
#3 "Webpack и Vue.JS: Создание больших приложений и их расширение" Кирилл Кай...JSib
 
2016-08-20 02 Антон Ковалев, Антон Кормаков. Viper. Чистая архитектура для iOS
2016-08-20 02 Антон Ковалев, Антон Кормаков. Viper. Чистая архитектура для iOS2016-08-20 02 Антон Ковалев, Антон Кормаков. Viper. Чистая архитектура для iOS
2016-08-20 02 Антон Ковалев, Антон Кормаков. Viper. Чистая архитектура для iOSОмские ИТ-субботники
 
Модульная структура. Цветцих Денис D2D Just.NET
Модульная структура. Цветцих Денис D2D Just.NETМодульная структура. Цветцих Денис D2D Just.NET
Модульная структура. Цветцих Денис D2D Just.NETDev2Dev
 
Как навести порядок в коде вашего web-приложения, Андрей Чебукин
Как навести порядок в коде вашего web-приложения, Андрей Чебукин Как навести порядок в коде вашего web-приложения, Андрей Чебукин
Как навести порядок в коде вашего web-приложения, Андрей Чебукин Sigma Software
 
iOS and Android Mobile Test Automation
iOS and Android Mobile Test AutomationiOS and Android Mobile Test Automation
iOS and Android Mobile Test AutomationAndrii Dzynia
 
Mobile automation uamobile
Mobile automation uamobileMobile automation uamobile
Mobile automation uamobileUA Mobile
 
Разработка Windows 8 приложений глазами WPF/Silverlight программиста
Разработка Windows 8 приложений глазами WPF/Silverlight программистаРазработка Windows 8 приложений глазами WPF/Silverlight программиста
Разработка Windows 8 приложений глазами WPF/Silverlight программистаDotNetConf
 
"Погружение в Robolectric" Дмитрий Костырев (Avito)
"Погружение в Robolectric"  Дмитрий Костырев (Avito)"Погружение в Robolectric"  Дмитрий Костырев (Avito)
"Погружение в Robolectric" Дмитрий Костырев (Avito)AvitoTech
 

Ähnlich wie Разработка WPF приложений в стиле ViewModel First (20)

MVVM в WinForms – DevExpress Way (теория и практика)
MVVM в WinForms – DevExpress Way (теория и практика)MVVM в WinForms – DevExpress Way (теория и практика)
MVVM в WinForms – DevExpress Way (теория и практика)
 
Viper - чистая архитектура iOS-приложения (И. Чирков)
Viper - чистая архитектура iOS-приложения (И. Чирков)Viper - чистая архитектура iOS-приложения (И. Чирков)
Viper - чистая архитектура iOS-приложения (И. Чирков)
 
Антон Валюх - Использование паттерна Mvvm в android
Антон Валюх - Использование паттерна Mvvm в androidАнтон Валюх - Использование паттерна Mvvm в android
Антон Валюх - Использование паттерна Mvvm в android
 
Курсы по мобильной разработке. 2 лекция. Построение интерфейсов в iOS
Курсы по мобильной разработке. 2 лекция. Построение интерфейсов в iOSКурсы по мобильной разработке. 2 лекция. Построение интерфейсов в iOS
Курсы по мобильной разработке. 2 лекция. Построение интерфейсов в iOS
 
AndroidMVPHelper
AndroidMVPHelperAndroidMVPHelper
AndroidMVPHelper
 
C# Web. Занятие 11.
C# Web. Занятие 11.C# Web. Занятие 11.
C# Web. Занятие 11.
 
#MBLTdev: Опыт использования MVVM в реальных проектах
#MBLTdev: Опыт использования MVVM в реальных проектах#MBLTdev: Опыт использования MVVM в реальных проектах
#MBLTdev: Опыт использования MVVM в реальных проектах
 
Веселая ферма. Соседи.
Веселая ферма. Соседи.Веселая ферма. Соседи.
Веселая ферма. Соседи.
 
Школа-Студия разработки приложений для iOS. 5 лекция. Разное
Школа-Студия разработки приложений для iOS. 5 лекция. РазноеШкола-Студия разработки приложений для iOS. 5 лекция. Разное
Школа-Студия разработки приложений для iOS. 5 лекция. Разное
 
'The best practices' by KONSTANTIN KULAKSYZ at OdessaJS'2020
'The best practices' by KONSTANTIN KULAKSYZ at OdessaJS'2020'The best practices' by KONSTANTIN KULAKSYZ at OdessaJS'2020
'The best practices' by KONSTANTIN KULAKSYZ at OdessaJS'2020
 
#3 "Webpack и Vue.JS: Создание больших приложений и их расширение" Кирилл Кай...
#3 "Webpack и Vue.JS: Создание больших приложений и их расширение" Кирилл Кай...#3 "Webpack и Vue.JS: Создание больших приложений и их расширение" Кирилл Кай...
#3 "Webpack и Vue.JS: Создание больших приложений и их расширение" Кирилл Кай...
 
2016-08-20 02 Антон Ковалев, Антон Кормаков. Viper. Чистая архитектура для iOS
2016-08-20 02 Антон Ковалев, Антон Кормаков. Viper. Чистая архитектура для iOS2016-08-20 02 Антон Ковалев, Антон Кормаков. Viper. Чистая архитектура для iOS
2016-08-20 02 Антон Ковалев, Антон Кормаков. Viper. Чистая архитектура для iOS
 
Views обзор
Views обзорViews обзор
Views обзор
 
Модульная структура. Цветцих Денис D2D Just.NET
Модульная структура. Цветцих Денис D2D Just.NETМодульная структура. Цветцих Денис D2D Just.NET
Модульная структура. Цветцих Денис D2D Just.NET
 
Как навести порядок в коде вашего web-приложения, Андрей Чебукин
Как навести порядок в коде вашего web-приложения, Андрей Чебукин Как навести порядок в коде вашего web-приложения, Андрей Чебукин
Как навести порядок в коде вашего web-приложения, Андрей Чебукин
 
MWWM
MWWMMWWM
MWWM
 
iOS and Android Mobile Test Automation
iOS and Android Mobile Test AutomationiOS and Android Mobile Test Automation
iOS and Android Mobile Test Automation
 
Mobile automation uamobile
Mobile automation uamobileMobile automation uamobile
Mobile automation uamobile
 
Разработка Windows 8 приложений глазами WPF/Silverlight программиста
Разработка Windows 8 приложений глазами WPF/Silverlight программистаРазработка Windows 8 приложений глазами WPF/Silverlight программиста
Разработка Windows 8 приложений глазами WPF/Silverlight программиста
 
"Погружение в Robolectric" Дмитрий Костырев (Avito)
"Погружение в Robolectric"  Дмитрий Костырев (Avito)"Погружение в Robolectric"  Дмитрий Костырев (Avito)
"Погружение в Robolectric" Дмитрий Костырев (Avito)
 

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

  • 1. Разработка WPF приложений в стиле ViewModel First Денис Цветцих АстроСофт http://www.astrosoft.ru/ 11-я конференция .NET разработчиков 31 октября 2015 dotnetconf.ru
  • 2. 2 Почему это актуально • WPF все ещё жив  • MVVM – тема множества докладов и статей • Множество разных реализаций • от MVVM.Light • до Prism с мануалом на 250 страниц
  • 3. 3 В чем проблема? Много разных реализаций MVVM • Непонятно, чем они отличаются • Непонятно, какую из них использовать и в каких случаях
  • 4. 4 Почему я здесь • Накоплен интересный опыт участия в WPF проектах • Есть опыт, связанный с фреймворками: • Использование сторонних • Доработка сторонних • Изобретение своего MVVM фреймворка 
  • 5. 5 Опрос • Кто собирается написать WPF приложение? • Кто при этом использовал какие-нибудь MVVM библиотеки/фреймворки? • Кто их вас изобрел свой собственный MVVM велосипед фреймворк?
  • 6. 6 О чем мы поговорим? • Что такое MVVM? • Какими бывают подходы к его реализации? • Как отличаются организация CompositeUI и дочерних окон в разных подходах? • Какой подход лучше использовать? • Где найти реализацию этого подхода? • Рекомендации на основе нашего опыта
  • 8. 8 Что со всем этим делать? Как решать типовые задачи? • CompositeUI (MasterDetail форма) • Навигация (дочерние окна)
  • 9. 9 Нам нужен MVVM фреймворк! Бывает 2 типов: • ViewFirst • ViewModelFirst Это не разные реализации паттерна MVVM Это разные подходы к решению типовых задач с использованием MVVM
  • 12. 12 ViewFirst (Prism) Отображение нового региона: 1) Создать View 2) Создать ViewModel для View 3) View.DataContext = ViewModel 4) Инициализировать ViewModel
  • 14. 14 UserListView <Grid> <TextBlock Grid.Row="0" Text="User list" FontWeight="Bold" /> <ListBox Grid.Row="1" x:Name="UserListBox" SelectedItem="{Binding SelectedUser, Mode=TwoWay}" ItemsSource="{Binding Users}"> <ListBox.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding FirstName}" /> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </Grid> public UserListView() { DataContext = new UserListViewModel(); }
  • 15. 15 UserDetailsView <StackPanel Orientation="Vertical"> <TextBlock Text="User details" FontWeight="Bold" /> <TextBlock Text="{Binding User.FirstName}" /> <TextBlock Text="{Binding User.LastName}" /> </StackPanel> public UserDetailsView() { DataContext = new UserDetailsViewModel(); }
  • 16. 16 UserListViewModel public class UserListViewModel : ViewModel { private User _selectedUser; public IEnumerable<User> Users { get; } // инициализация public User SelectedUser { get { return _selectedUser; } set { _selectedUser = value; OnPropertyChanged(); } } }
  • 17. 17 UserDetailsViewModel public class UserDetailsViewModel : ViewModel { private User _user; public User User { get { return _user; } set { _user = value; OnPropertyChanged(); } } }
  • 18. 18 Вопрос Как сделать так, чтобы UserListViewModel.SelectedUser синхронизировалось с UserDetailsViewModel.User? Ответ в стиле ViewFirst – MessageBus
  • 20. 20 MessageBus public class MessageBus { public static MessageBus Instance = new MessageBus(); public event EventHandler<UserChangedEventArgs> 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; } }
  • 21. 21 UserListViewModel public class UserListViewModel : ViewModel { public User SelectedUser { get { return _selectedUser; } set { _selectedUser = value; OnPropertyChanged(); MessageBus.Instance.OnSelectedUserChanged(value); } } }
  • 22. 22 UserDetailsViewModel public class UserDetailsViewModel : ViewModel { public UserDetailsViewModel() { MessageBus.Instance.SelectedUserChanged += (s, e) => User = e.User; } }
  • 23. 23 Недостатки 1) Используется MessageBus, предназначенный для интеграции систем 2) На широковещательное событие может подписаться любой объект 3) Поведение системы становится запутанным и неочевидным
  • 24. 24 ViewModelFirst (энтузиасты) Отображение нового региона: 1) Создать ViewModel 2) Инициализировать ViewModel 3) Создать View для ViewModel 4) View.DataContext = ViewModel
  • 25. 25 Чистим CodeBehind public UserListView() { DataContext = new UserListViewModel(); } public UserDetailsView() { DataContext = new UserDetailsViewModel(); }
  • 26. 26 Убираем MessageBus public class UserListViewModel : ViewModel { public User SelectedUser { get { return _selectedUser; } set { _selectedUser = value; OnPropertyChanged(); MessageBus.Instance.OnSelectedUserChanged(value); } } }
  • 27. 27 Убираем MessageBus public class UserDetailsViewModel : ViewModel { public UserDetailsViewModel() { MessageBus.Instance.SelectedUserChanged += (s, e) => User = e.User; } }
  • 28. 28 Вопрос Как сделать так, чтобы UserListViewModel.SelectedUser синхронизировалось с UserDetailsViewModel.User? Ответ в стиле ViewModelFirst – нам нужна родительская ViewModel
  • 29. 29 MainWindowViewModel 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; }; } }
  • 30. 30 MainWindow <Grid> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition /> </Grid.ColumnDefinitions> <views:UserListView DataContext="{Binding UserListViewModel}" Grid.Column="0" /> <views:UserDetailsView DataContext="{Binding UserDetailsViewModel}" Grid.Column="1" /> </Grid>
  • 31. 31 ViewFirst vs ViewModelFirst ViewFirst ViewModelFitst CompositeUI да да Взаимодействие ViewModel MessageBus Родетельская ViewModel
  • 33. 33 ViewFirst: показать новый элемент Дочернее окно, новый таб: Navigation.Show<ViewModel>(Value); или Navigation.Show("View", Value); Аналогично вебу: http://address.ru/?arg=value ViewFirst предлагает в WPF организовать навигацию аналогично веб-приложению
  • 34. 34 ViewModelFirst: показать новый элемент var vm = Navigation.Get<ViewModel>(); vm.Arg = Value; vm.Show(); Аналогично окну WPF: var wnd = new Window(); wnd.Arg1 = Value1; wnd.Show();
  • 35. 35 ViewFirst vs ViewModelFirst ViewFirst ViewModelFirst Создать View Создать ViewModel Создать ViewModel Инициализировать ViewModel Инициализировать ViewModel Создать View View.DataContext = ViewModel View.DataContext = ViewModel
  • 37. 37 Отображение дочернего окна private void OnShowDetails(User user) { var detailsVM = Factory.Resolve<UserDetailsWindowViewModel>(); detailsVM.User = user; detailsVM.Closed += (s, e) => { /* обработка e.DialogResult */ }; detailsVM.Show(); }
  • 38. 38 ChildViewModel 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); } }
  • 39. 39 ChildViewModelManager public class ChildViewModelManager : IChildViewModelManager { // открытые окна private readonly Dictionary<Type, Window> _openedWindows = new Dictionary<Type, Window>(); // по типу ViewModel возвращает View [Dependency] public IViewTypeResolver ViewTypeResolver { private get; set; } }
  • 40. 40 ChildViewModelManager: 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(); }
  • 41. 41 ChildViewModelManager: Close public void Close(IChildViewModel viewModel) { // какое окно закрываем var window = _openedWindows[viewModel.GetType()]; // убираем из списка открытых _openedWindows.Remove(viewModel.GetType()); // закрываем Application.Current.Dispatcher.BeginInvoke( new Action(() => window.Close()), null); }
  • 42. 42 ChildWindow 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(); } } }
  • 43. 43 Особенности ViewModelFirst Достоинства • Позволяет реализовать CompositeUI • Не требует реализации MessageBus • Взаимодействие ViewModel более очевидное • Нет MessageBus – нет его использования не по назначению • Позволяет удобно реализовать поддержку дочерних окон Недостатки • Не имеет вендорской поддержки
  • 44. 44 Наш рецепт • ViewModelFirst • Свой велосипед • Mugen MVVM Toolkit • IoC контейнер • ReactiveUI (ограничено) • ReactiveCommand • ObservableForProperty • Отдельная сборка для ViewModel
  • 45. 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/
  • 46. 46 Спасибо за внимание Денис Цветцих АстроСофт den.tsvettsih@yandex.ru

Hinweis der Redaktion

  1. Рассказать что было много WPF проектов, было набито много шишек, использованы чужие MVVM. Доработаны чужие, изобретены свои. Есть опыт, которым хочется поделиться. История про красноярский и новгородский офис
  2. Добавить картинок