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

时间:2011-06-09 06:21:21

标签: wpf navigation unity-container prism

我在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)处休息,但这种方法似乎永远不会被调用。

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

2 个答案:

答案 0 :(得分:7)

问题出现在我从未想过的地方......调试导航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"

Everthing工作。

<强>结论

  

必须启动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);

答案 1 :(得分:0)

注册View和ViewModel是个问题。要只有一个视图,您必须使用不同的生命周期管理器。如果不指定生命周期管理器,则使用TransientLifetimeManager,它始终在resolve上返回新实例。要只有一个实例,您必须使用ContainerControlledLifetimeManagerHierarchicalLifetimeManager

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