2011-06-09 17 views
6

Estoy usando PRISM 4 Navigation API con Unity en WPF. Tengo una vista en árbol que inicia un RequestNavigate pasando el ID del nodo del árbol seleccionado (GUID).PRISM WPF: la navegación crea una nueva vista cada vez

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

En mi módulo, que han registrado la vista/foto-modelo de este modo:

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

Cuando selecciono diferentes nodos de la vista de árbol, la DetailsRegion muestra el SiteDetailsView como esperado, pero cuando me gusta navegar de vuelta al mismo nodo, se crea una nueva vista/modelo de vista.

Traté de romper en IsNavigationTarget(NavigationContext navigationContext) pero este método parece que nunca se llamará.

¿Dónde me he equivocado? Gracias por adelantado.

Respuesta

7

El problema estaba en un lugar tal que nunca esperé ... Depuración del API de navegación me llevan a la RegionNavigationContentLoader

public object LoadContent(IRegion region, NavigationContext navigationContext) 

cuando entré más abajo en el código, me di cuenta de una llamada a:

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

me di cuenta que el nombramiento aquí es clave para que coincida la vista al modelo de vista.

En mi ejemplo, el nombre de cada parte fue:

public class SiteDetailsViewModel { ... } // ViewModel 

public class SiteDetailsView { ... } // View 

ViewNames.SiteView = "SiteView" // ViewName constant 

Cuando inadvertidamente hice el siguiente cambio:

ViewName.SiteView = "SiteDetailsView" 

Everthing trabajó.

Conclusión

El nombre del modelo de vista debe comenzar con el mismo nombre que utilizó para identificar su punto de vista.

He probado esto a cabo por el cambio de mi fin de:

public class MyView { ... } 

y sigue utilizando el mismo nombre de la vista que se registra en el contenedor y la navegación:

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

... 

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

Esto parece funcionar también .Por lo tanto, parece que el nombre de View-Model está intrínsecamente vinculado al nombre de vista utilizado para navegar a esa vista.

NOTA

Esto es sólo cuando se está utilizando la COI y la unidad con la API de PRISM 4 de navegación. Esto no parece suceder cuando se usa MEF.

Investigación Adicional

También soy consciente de que algunos guides nos han dicho a utilizar el typeof(MyView).FullName al registrar la vista con el contenedor ...

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

Yo personalmente creo que esto es un error . Al usar el nombre completo de la vista, está creando una dependencia entre la vista y cualquiera que desee navegar a esa vista ...

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

sí, comportamiento extraño, encontré esta información en los comentarios a este número http://compositewpf.codeplex.com/workitem/7468?PendingVoteId=7468 –

0

El registro de View y ViewModel es el problema. Para tener una sola vista, debe usar un administrador de vida diferente. Sin especificar un administrador de por vida, se usa TransientLifetimeManager, que siempre devuelve una nueva instancia en resolver. Para tener sólo una única instancia que tiene que utilizar el ContainerControlledLifetimeManager o la HierarchicalLifetimeManager:

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

Esto no solucionó el problema. –

Cuestiones relacionadas