Tuesday, September 14, 2010

MVVM Light Toolkit overview

В предыдущих двух статьях про MVVM для создания примеров я пользовался только стандартными средствами, которые out of box предоставляет WPF. Для очень простых случаев, возможно, такой подход и оправдан. Недостаток его в том, что приходится писать много plumbing кода. А это рутина, от которой всегда хочется избавиться.

Для имплементации команды AddNewTagCommand мы создавали приватный класс во ViewModel. Но у нас была всего одна команда. Если понадобится больше команд, то писать для каждой из них свой класс – не самая лучшая идея. Надо будет каким-то образом выносить общую функциональность.

Наш ViewModel реализовывал интерфейс INotifyPropertyChanged. Дублировать его реализацию в каждом ViewModel нехорошо. Поэтому ее тоже надо выносить, например, в базовый класс.

Не смотря на все удобство команд, они почему-то поддерживаются только контролами производными от ButtonBase и только для события Click. Что же делать, если вы хотите использовать команду для реакции на SelectionChanged у ListBox’a? Написать свой собственный behavior, который сможет привязать команду к произвольному событию.

Для того чтобы использовать эти наработки в других своих WPF приложениях, наверняка вы вынесете их в отдельную библиотеку. Поздравляю, вы написали свой собственный MVVM Toolkit! :)

На самом деле MVVM – это просто паттерн, и для его применения не нужны никакие тулкиты. Все тулкиты – это просто хэлперы, которые облегчают вам жизнь, избавляя от рутины. Список желающих помочь вам оказался настолько внушительным, что я отказался от первоначальной идеи делать обзор и сравнение их всех. Итак, согласно Википедии сейчас существует 14 различных MVVM toolkit’ов:

Для полноты картины следует добавить сюда еще PRISM (который, на самом деле, гораздо больше чем просто очередной MVVM toolkit) и nRote.

В комментариях в блоге MVVM Light Toolkit автора спросили: «Laurent, почему ты написал свой собственный тулкит? Ведь ты общаешься со столькими WPF гуру, каждый из которых, кстати, тоже написал свой тулкит :) Так почему же вы, парни, не пообщались и не написали что-то одно? Вместо того чтобы запутывать людей этой горой тулкитов, функционал которых пересекается на 90% и отличается нюансами имплементации.»

Я хочу привести здесь ответ, потому что он достаточно четко описывает идеи заложенные в MVVM Light Toolkit: «I think that the main reason is that we have different reasons to use (and make) such a framework. For me, the main reason is really Blendability (design time data, specifically), with testability of the UI a close second. For others, validation plays a very large role in their adoption of the MVVM pattern, etc. In addition, to be useful to me, a framework needs to work in Silverlight as well as in WPF, while others do not care about Silverlight (yet?) and find it too limited. I cannot rely on WPF-only mechanisms in my framework, but others do because their craft is in a different area than mine.

For what it is worth, there is quite an intense collaboration between some of the disciples and me on this toolkit. The toolkit I provide is a "blend" (pun intended) of code and ideas coming from different sources. The credits section on the Get Started page lists some of the major contributors, most of them from the disciples group. I have fished many ideas and solved many problems on the group.

Lastly, I would be a bit reluctant to engage in a large scale operation to provide a "one and only" MVVM framework. To be blunt, it sounds like a lot less fun than what I am doing now. The good news is that many at Microsoft are aware of this effort, and I think we will see improvements in the framework (WPF and Silverlight) directly that should make some of this toolkit redundant. This is why I put a lot of effort in keeping it "light", because I am pretty sure it will be obsolete some day.»

Итак, MVVM Light Toolkit – это легковесная библиотека классов, которая упростит вам жизнь, избавив от рутины при имплементации MVVM паттерна для WPF, Silverlight и Windows Phone 7 приложений. Давайте посмотрим, что именно предлагает этот тулкит:

  1. Классы RelayCommand и RelayCommand<T>. Реализуют интерфейс ICommand для WPF и Silverlight. Упрощают создание команд.
  2. Класс ViewModelBase может быть использован как базовый для всех ViewModel’ов. Избавляет от необходимости реализовывать INotifyPropertyChanged.
  3. EventToCommand behavior позволяет привязывать команды к любым событиям любых UI контролов.
  4. Класс Messenger позволяет организовывать обмен сообщениями внутри приложения.
  5. Класс DispatcherHelper облегчает жизнь при работе с потоками.

Список небольшой, но минимально достаточный. Если для решения ваших задач вам чего-то не хватает, то смотрите на другие фреймворки из приведенного выше списка. Я же перейду от слов к коду и покажу какие изменения произойдут в демо приложении, которое мы создали в предыдущих статьях.

Давайте начнем с команд. Т.к. Теперь у нас есть RelayCommand, то мы можем избавиться от класса CustomCommand. Теперь команда AddNewTagCommand будет выглядеть вот так:

public ICommand _addNewTagCommand;
public ICommand AddNewTagCommand
{
get
{
if (_addNewTagCommand == null)
_addNewTagCommand = new RelayCommand(AddNewTagExecute);

return _addNewTagCommand;
}
}

public void AddNewTagExecute()
{
Tags.Add(NewTag);
NewTag = string.Empty;
}

Обратите внимание, что логика команды переехала во ViewModel.

Кроме реализации ICommand из нашего ViewModel ушла также и реализация INotifyPropertyChanged. Вместо этого теперь наш ViewModel наследуется от ViewModelBase, в котором INotifyPropertyChanged уже реализован.

public sealed class MainViewModel : ViewModelBase

На этом все. В следующей статье я рассмотрю примеры использования EventToCommand behavior’a, Messenger’a и DispatcherHelper’a.

Исходный код можно скачать отсюда

2 comments:

  1. Спасибо, очень точно и по сути самое главное.

    ReplyDelete
  2. скачал версию 5.2.0 от 31.08.2015, эта версия совсем не соответствует описанию... компоненты другие...

    ReplyDelete