Главная » C#, Windows Runtime, XAML, Разработка для Windows 8 » Использование паттерна MVVM

0

Такая  мощная  модель  связывания  данных  позволяет использовать  паттерн

MVVM для архитектуры приложения.

Данный  паттерн  был  представлен Джоном  Госсманом  в    2005   году.  Он представляет модификацию  паттерна MVP и ориентирован  на современные платформы  разработки,  которые  имеют   возможность связывания данных. Благодаря   применению   этого   паттерна   у   нас   появляется  возможность разделения  представления  и  модели,  тем  самым  мы  можем  изменять  их независимо друг  от  друга.  Например, разработчики  создают логику  работы приложения, а дизайнеры работают над интерфейсом приложения.

Этот  паттерн  следует  применять,  если  в   технологии  присутствует  механизм связывания  данных.  Использование паттерна  MVC/MVP  в  таких  случаях  не вкладывается в их концепцию.

Паттерн MVVM делится на три части (Рис. 5.3):

·                   Model  —  представляет фундаментальные  данные,  необходимые  для работы приложения;

·                   View — это графический интерфейс нашего приложения;

·                   ViewModel — является с одной стороны абстракцией View, а с другой — предоставляет обертку данных из Model, которые подлежат связыванию. То есть она содержит Model, которая  преобразована  к View, а так же содержит команды, которыми может пользоваться View, чтобы влиять на Model.

Рис. 5.3.

Классическая реализация базовой ViewModel:

public class ViewModel : INotifyPropertyChanged

{

public event PropertyChangedEventHandler PropertyChanged;

protected void RaisePropertyChanged(string propertyName)

{

var handler = PropertyChanged; if (handler != null)

{

handler(this, new PropertyChangedEventArgs(propertyName));

}

}

}

Далее,  разделение  логики  на  модели  ViewModel  происходит  отдельно  для каждого проекта. Все последующие ViewModel являются наследниками базовой. Например, возьмем наш тип данных Employee и реализуем для него ViewModel (обратите внимание, что создавать ViewModel по принципу для каждой Model своя ViewModel — неправильно!)

public class EmployeeViewModel : ViewModel

{

public ObservableCollection<Employee> EmployeeCollection { get; private set; }

public ICommand AddEmployee { get; private set; } public ICommand EditEmployee { get; private set; } public ICommand DeleteEmplyee { get; private set; }

public EmployeeViewModel()

{

EmployeeCollection = new ObservableCollection<Employee>

{

new Employee { FirstName="Sergii", LastName="Lutai", Age=27, EMail="sergii.lutai@dct.ua"},

new Employee { FirstName="Sergiy", LastName="Baydachnyy", Age=32, EMail="Sergiy.Baydachnyy@microsoft.com"},

new Employee { FirstName="Ivan", LastName="Ivanov", Age=29, EMail="ivan@ivanov.ua"}

};

AddEmployee = new RelayCommand<Employee> (this.AddEmployeeExecute, this.AddEmployeeCanExecute);

}

private void AddEmployeeExecute(Employee employee)

{

//TODO: Логика добавления объекта

}

private bool AddEmployeeCanExecute(Employee employee)

{

//TODO: Логика проверки возможности добавления нового объекта

return employee != null;

}

}

В  данном  примере  класс   RelayCommand  является одной  из   возможных реализаций интерфейса System.Windows.Input.RelayCommand:

public class RelayCommand<T>: ICommand

{

private Action<T> action; private Func<T, bool> func;

public RelayCommand(Action<T> action)

{

this.action = action;

}

public RelayCommand(Action<T> action, Func<T, bool> func)

{

this.action = action; this.func = func;

}

public bool CanExecute(object parameter)

{

bool result = true;

T value = default(T);

if (parameter != null && !(parameter is T))

{

«parameter");

}

throw new ArgumentException(«Wrong parameter type.",

if (parameter != null)

{

value = (T)parameter;

}

if (func != null)

{

result = func(value);

}

return result;

}

public event EventHandler CanExecuteChanged;

public void Execute(object parameter)

{

T value = default(T);

if (parameter != null && !(parameter is T))

{

«parameter");

}

throw new ArgumentException(«Wrong parameter type.",

if (parameter != null)

{

value = (T)parameter;

}

var canExecute = CanExecute(value); if (canExecute)

{

action(value);

}

}

public void RaiseCanExecuteChanged()

{

var handler = CanExecuteChanged; if (handler != null)

{

handler(this, EventArgs.Empty);

}

}

}

Для проверки нашей логики будем использовать следующее представление:

<Page x:Class="MVVM.Sample.BlankPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:MVVM.Sample" xmlns:viewModel="using:ViewModel">

<Page.Resources>

<viewModel:EmployeeViewModel x:Key="EmployeeViewModel"/>

</Page.Resources>

<Page.DataContext>

<Binding Source="{StaticResource EmployeeViewModel}"/>

</Page.DataContext>

<Grid Background="{StaticResource ApplicationPageBackgroundBrush}">

<Button Content="Add New Employee" VerticalAlignment="Top" Command="{Binding AddEmployee, Mode=OneTime,

Source={StaticResource EmployeeViewModel}}"/>

<ListBox ItemsSource="{Binding EmployeeCollection}" Margin="0,40,0,0">

<ListBox.ItemTemplate>

<DataTemplate>

<StackPanel Orientation="Horizontal">

<Button Content="Delete" Command="{Binding DeleteEmplyee, Mode=OneWay, Source={StaticResource EmployeeViewModel}}" CommandParameter="{Binding Mode=OneWay}"/>

<Button Content="Edit" Command="{Binding EditEmployee, Mode=OneWay, Source={StaticResource EmployeeViewModel}}" CommandParameter="{Binding Mode=OneWay}"/>

<TextBlock Text="{Binding FirstName}"

Margin="40,0,40,0"/>

<TextBlock Text="{Binding LastName}"/>

</StackPanel>

</DataTemplate>

</ListBox.ItemTemplate>

</ListBox>

</Grid>

</Page>

Во время работы наш пример имеет следующий вид:

Рис. 5.4.

Рис. 5.5.

Таким   образом,  используя  паттерн  MVVM,  мы  можем  разделить   работу дизайнеров и разработчиков.  Что в свою   очередь позволяет  сосредоточиться именно на логике бизнес-процессов внутри приложения. При этом возможность тестирования бизнес-логики  приложения увеличивается в  разы. Возможность тестирования будет рассмотрена в главе 12.

Сергей Лутай, Сергей Байдачный, Windows 8 для C# разработчиков

По теме:

  • Комментарии