PRISM WPF - навигация создает новый вид каждый раз - PullRequest
6 голосов
/ 09 июня 2011

Я использую PRISM 4 Navigation API с Unity в WPF.У меня есть древовидное представление, которое инициирует RequestNavigate , передающий идентификатор выбранного узла дерева ( GUID ).

_regionManager.RequestNavigate(RegionNames.DetailRegion,
    ViewNames.SiteView + "?ID=" + site.ID);

В моем модуле я зарегистрировалview / view-model примерно так:

_container.RegisterType<SiteDetailsViewModel>();
_container.RegisterType<object, SiteDetailsView>(ViewNames.SiteView);

Когда я выбираю разные узлы из древовидного представления, DetailsRegion отображает SiteDetailsView , как и ожидалось, но когда янравится возвращаться к тому же узлу, создается новое представление / модель представления.

Я пытался разбить на IsNavigationTarget(NavigationContext navigationContext), но этот метод, кажется, никогда не вызывается.

Где естья ошибся?Заранее спасибо.

Ответы [ 2 ]

7 голосов
/ 10 июня 2011

Проблема была в таком месте, что я никогда не ожидал ... Отладка API навигации приводит меня к RegionNavigationContentLoader

public object LoadContent(IRegion region, NavigationContext navigationContext)

Когда я шагнул дальше по коду, я заметил вызов:

protected virtual IEnumerable<object> GetCandidatesFromRegion(
    IRegion region,
    string candidateNavigationContract)

Я заметил, что наименование здесь является ключом к сопоставлению вида с моделью представления.

В моем примере имя для каждой части было:

public class SiteDetailsViewModel { ... } // ViewModel

public class SiteDetailsView { ... } // View

ViewNames.SiteView = "SiteView" // ViewName constant

Когда я случайно сделал следующее изменение:

ViewName.SiteView = "SiteDetailsView"

Все работает.

Заключение

Имя ViewModel должно начинаться с тем же именем, которое вы использовали для определите ваше мнение.

Я проверил это, изменив мой взгляд на:

public class MyView { ... }

и все еще используя то же имя представления для регистрации в контейнере и навигации:

_container.RegisterType<object, MyView>(ViewNames.SiteView);

...

_regionManager.RequestNavigate(RegionNames.DetailRegion,
    ViewNames.SiteView + "?ID=" + site.ID);

Кажется, это тоже работает. Таким образом, кажется, что имя View-Model неразрывно связано с именем представления, используемым для перехода к этому представлению.

Примечание

Это только когда вы используете IoC и Unity с PRISM 4 Navigation API. Похоже, этого не происходит при использовании MEF.

Дальнейшее расследование

Мне также известно, что некоторые направляющие говорят нам использовать typeof(MyView).FullName при регистрации представления с Контейнером ...

_container.RegisterType<object, MyView>(typeof(MyView).FullName);

Лично я считаю, что это ошибка. Используя полное имя представления, вы создаете зависимость между представлением и любым, кто хочет перейти к этому представлению ...

_regionManager.RequestNavigate(RegionNames.DetailRegion,
    typeof(MyView).FullName + "?ID=" + site.ID);
0 голосов
/ 09 июня 2011

Регистрация View и ViewModel является проблемой.Чтобы иметь только одно представление, вы должны использовать другой менеджер времени жизни.Без указания администратора времени жизни используется TransientLifetimeManager, который всегда возвращает новый экземпляр при разрешении.Чтобы иметь только один экземпляр, вы должны использовать ContainerControlledLifetimeManager или HierarchicalLifetimeManager:

_container.RegisterType<SiteDetailsViewModel>(new ContainerControlledLifetimeManager());
_container.RegisterType<object, SiteDetailsView>(ViewNames.SiteView, new ContainerControlledLifetimeManager());
...