【问题标题】:PRISM WPF - Navigation creates new view every timePRISM WPF - 导航每次都会创建新视图
【发布时间】: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) 中断,但这个方法似乎永远不会被调用。

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

【问题讨论】:

    标签: wpf navigation unity-container prism


    【解决方案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);
    

    【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-27
      • 2018-03-22
      • 1970-01-01
      • 2014-04-25
      相关资源
      最近更新 更多