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

Tri*_*ran 6 navigation wpf prism unity-container

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

_regionManager.RequestNavigate(RegionNames.DetailRegion,
    ViewNames.SiteView + "?ID=" + site.ID);
Run Code Online (Sandbox Code Playgroud)

在我的模块中,我已经注册了view/view-model,如下所示:

_container.RegisterType<SiteDetailsViewModel>();
_container.RegisterType<object, SiteDetailsView>(ViewNames.SiteView);
Run Code Online (Sandbox Code Playgroud)

当我从树视图中选择不同的节点时,DetailsRegion会按预期显示SiteDetailsView,但是当我想导航回同一节点时,会创建一个新的视图/视图模型.

我试图打破,IsNavigationTarget(NavigationContext navigationContext)但这种方法似乎永远不会被调用.

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

Tri*_*ran 7

问题是在这样一个我从没想过的地方......调试导航API引导我进入 RegionNavigationContentLoader

public object LoadContent(IRegion region, NavigationContext navigationContext)
Run Code Online (Sandbox Code Playgroud)

当我进一步深入代码时,我注意到一个电话:

protected virtual IEnumerable<object> GetCandidatesFromRegion(
    IRegion region,
    string candidateNavigationContract)
Run Code Online (Sandbox Code Playgroud)

我注意到这里的命名是将视图与视图模型匹配的关键.

在我的例子中,每个部分的名称是:

public class SiteDetailsViewModel { ... } // ViewModel

public class SiteDetailsView { ... } // View

ViewNames.SiteView = "SiteView" // ViewName constant
Run Code Online (Sandbox Code Playgroud)

当我无意中做出以下改变时:

ViewName.SiteView = "SiteDetailsView"
Run Code Online (Sandbox Code Playgroud)

Everthing工作.

结论

ViewModel的名称必须以您用于标识视图的名称开头.

我通过将我的观点更改为:

public class MyView { ... }
Run Code Online (Sandbox Code Playgroud)

并且仍然使用相同的视图名称来注册容器和导航:

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

...

_regionManager.RequestNavigate(RegionNames.DetailRegion,
    ViewNames.SiteView + "?ID=" + site.ID);
Run Code Online (Sandbox Code Playgroud)

这似乎也有效.因此,View-Model的名称似乎与用于导航到该视图的视图名称本质上相关联.

注意

这只是在您使用IoC和Unity与PRISM 4 Navigation API时.使用MEF时似乎不会发生这种情况.

进一步的调查

我也知道有些导游告诉我们在使用typeof(MyView).FullNameContainer注册视图时使用...

_container.RegisterType<object, MyView>(typeof(MyView).FullName);
Run Code Online (Sandbox Code Playgroud)

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

_regionManager.RequestNavigate(RegionNames.DetailRegion,
    typeof(MyView).FullName + "?ID=" + site.ID);
Run Code Online (Sandbox Code Playgroud)