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/
Добавить комментарий