MVVM Navigation toolkit для Windows Store и Windows Phone 8

от автора

Навигация в сабжевых платформах проста, но доставляет некоторый зуд в некоторых местах при попытке красиво связать ее с MVVM. К примеру, в Windows Phone навигация происходит только по ccылкам с возможностью задать параметры только в URI (т.е. строками) что особенно доставляет удовольствие при перемещении представлений в другие папки

Navigate(Uri uri)

тогда как в Windows Store интерфейс немного улучшили и дали возможность передавать объект

Navigate(Type pageType, object argument)

Тут есть интересная особенность – argument должен быть сериализуемым, иначе он пройдет на страницу успешно но поломает NavigationState (функция GetNavigationState зависнет при вызове).
Собственно, задача mvvm-навигации – это красивое связывание представлений с вьюмоделями и передача вьюмоделей при переходе на представления. Задавшись такой задачей я написал небольшой тулкит с примерами для Windows Store и Windows Phone.

Как это выглядит?

Регистрация

И так, сперва нам надо собственно связать представления с вьюмоделями (в качестве IoC я использую Autofac в примерах):

_navigationBuilder     .RegisterViewModel<FrameViewModel>().StaticResource().WithoutView()     .RegisterViewModel<MainViewModel>().Singleton().ForView<MainPage>()     .RegisterViewModel<NotesViewModel>().StaticResource().ForView<NotesView>()     .RegisterViewModel<NoteViewModel>().ForView<NoteView>()     .RegisterViewModel<AppSettingsViewModel>().ForView<AppSettingsView>()     ;


Как можно заметить, регистрация имеет fluent-стиль. StaticResource(), к примеру, означает, что вьюмодель будет доступна из XAML как StaticResource по имени как ключу. Т.е. в любом месте вы сможете написать что-нибудь типа

{Binding Notes.Count, Source={StaticResouce NotesViewModel}}

Singleton(), как и понятно из названия, зарегистрирует вьюмодель как синглитон в контейнере. ForView же выполнит главную задачу – сохранит маппинг вьюмодели с представлением. Использование тулкита потребует от вас реализовать интерфейс IIoCContainerBuilder (я решил не завязывать его на конкретные DI реализации типа Autofac), а так же отнаследовать все страницы от класса NavigatablePage.

Как открыть новую страницу из вьюмодели?

Внтри вьюмодели вы естественно ничего не знаете о представлении и поэтому переход осуществляется по средствам вызова метода Show (или ShowCommand) у целевой вьюмодели, который при помощи скрытой магии откроет страницу и передаст ей вьюмодель как DataContext. Т.е. можете в исходной вьюмодели хранить ссылку на целевую (через constructor\property injection) либо напрямую через ServiceLocator

ServiceLocator.Resolve<TargetViewModel>().Show();

Как работает передача вьюмодели на страницу?

Как я уже говорил, API не предлагает нормальных инструментов передачи сложных объектов как параметров к страницам, поэтому я обошёл проблему созданием специального реестра вьюмоделей (словарь пар Guid-ViewModel) и передачей идентификатора вьюмодели из реестра как строки в параметры к странице. Далее страница на OnNavigateTo достает вьюмодель по переданному ключу. Cделать это можно было и через MVVM Light Messanger, но я решил не добавлять лишние библиотеки в зависимости к тулкиту.

Заключение

Я описал малую часть тулкита и примеров, поэтому, советую с ними ознакомиться и надеюсь, что вы найдете некоторые интересные решения. По желанию, могу оформить это как шаблон проекта для Visual Studio.
git: github.com/EgorBo/MvvmNavigationToolkit

ссылка на оригинал статьи http://habrahabr.ru/post/189988/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *