PRISM WPF - Navigation creates a new look every time

I am using the PRISM 4 navigation API with Unity in WPF. I have a tree view that initiates the transmission of RequestNavigate in the selected tree node ID (GUID).

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

In my module, I registered the view / view model like this:

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

When I select different nodes from the tree view, DetailsRegion displays the SiteDetailsView as expected, but when I like to move back to the same node, a new view / view model is created.

I tried to break down on the IsNavigationTarget(NavigationContext navigationContext) , but this method is never called.

Where am I wrong? Thanks in advance.

+6
source share
2 answers

The problem was in a place that I never expected ... Debugging the navigation API led me to RegionNavigationContentLoader

 public object LoadContent(IRegion region, NavigationContext navigationContext) 

When I stepped further along the code, I turned to:

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

I noticed that naming here is key to matching the view with the view model.

In my example, the name for each part was:

 public class SiteDetailsViewModel { ... } // ViewModel public class SiteDetailsView { ... } // View ViewNames.SiteView = "SiteView" // ViewName constant 

When I accidentally made the following change:

 ViewName.SiteView = "SiteDetailsView" 

Work everthing.

Conclusion

The name of the ViewModel must begin with the same name with which you indicate your opinion.

I checked this by changing my view to:

 public class MyView { ... } 

and still use the same view name to register in the container and navigate:

 _container.RegisterType<object, MyView>(ViewNames.SiteView); ... _regionManager.RequestNavigate(RegionNames.DetailRegion, ViewNames.SiteView + "?ID=" + site.ID); 

This also works. Thus, it seems that the name of the View-Model is associated with the name of the view used to jump to this view.

Note

This is only when you use IoC and Unity with the PRISM 4 API. This is not like using MEF.

Further research

I also know that some tips told us to use typeof(MyView).FullName when registering a view with a container ...

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

I personally think this is a mistake. Using the full name of the view, you create dependencies between the view and anyone who wants to go to that view ...

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

Problem viewing View and ViewModel. To have only one look, you must use another life manager. Without a lifecycle manager, the TransientLifetimeManager used, which always returns a new instance when resolved. To have only one instance, you must use the ContainerControlledLifetimeManager or HierarchicalLifetimeManager :

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

Source: https://habr.com/ru/post/890118/


All Articles