PRISM WPF - 导航每次都会创建新视图

Posted

技术标签:

【中文标题】PRISM WPF - 导航每次都会创建新视图【英文标题】:PRISM WPF - Navigation creates new view every time 【发布时间】:2011-09-11 10:38:07 【问题描述】:

我在 WPF 中使用带有 Unity 的 PRISM 4 Navigation API。我有一个树视图,它启动一个 RequestNavigate,传入所选树节点的 ID (GUID)。

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

在我的模块中,我已经像这样注册了视图/视图模型:

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

当我从树视图中选择不同的节点时,DetailsRegion 会按预期显示 SiteDetailsView,但是当我想导航回同一个节点时,会出现一个新视图/view-model 已创建。

我试图在IsNavigationTarget(NavigationContext navigationContext) 中断,但这个方法似乎永远不会被调用。

我哪里出错了?提前致谢。

【问题讨论】:

【参考方案1】:

问题出在我没想到的地方...调试导航 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 时似乎不会发生这种情况。

进一步调查

我也知道一些guides 告诉我们在向容器注册视图时使用typeof(MyView).FullName...

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

我个人认为这是一个错误。通过使用视图的全名,您可以在视图和希望导航到该视图的任何人之间创建依赖关系...

_regionManager.RequestNavigate(RegionNames.DetailRegion,
    typeof(MyView).FullName + "?ID=" + site.ID);

【讨论】:

是的,奇怪的行为,我在 cmets 中找到了这个问题的信息compositewpf.codeplex.com/workitem/7468?PendingVoteId=7468【参考方案2】:

View 和 ViewModel 的注册是个问题。要只有一个视图,您必须使用不同的生命周期管理器。在不指定生命周期管理器的情况下,使用TransientLifetimeManager,它总是在解析时返回一个新实例。要只有一个实例,您必须使用ContainerControlledLifetimeManagerHierarchicalLifetimeManager

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

【讨论】:

以上是关于PRISM WPF - 导航每次都会创建新视图的主要内容,如果未能解决你的问题,请参考以下文章

在 Wpf 应用程序中使用 Prism 进行导航

Prism/MVVM (MEF/WPF):从模块中公开导航 [例如菜单]

WPF Prism 将参数从 idialog 发送回视图

05Prism WPF 入门实战 - Navigation

Prism:如何在区域中注入视图模型实例?

模态序列会创建新对象吗?