ParameterOverride in WPF/PRISM/MVVM

Topics: Prism v4 - WPF 4
Aug 6, 2012 at 9:01 PM
Edited Aug 6, 2012 at 9:03 PM

Hello all,

I have the following question; I am trying to use parameterOverride in conjenction with my view first approach in prism.  I have a command on productMainView, when the command fires, I have the following code:

var detailPage = _unityContainer.Resolve<ProductDetailView>(new ParameterOverride("ProductToOpen", dataItem).OnType<ProductDetailViewModel>());
_regionManager.RequestNavigate(RegionNames.MainRegion, new Uri(typeof(ProductDetailView).FullName, UriKind.Relative));

when we get to the detailPage variable, the constructor on my viewmodel is called and it has the correct dataItem pass into it.  Then I get another call when I set the "Dependecy" attribute on my view model in the view code behind like this

[Dependency] 
public ProductDetailViewModel ViewModel { set { DataContext = value; } }

However, the second time it calls the constructor the dataitem value is a new object. How can I ensure that I pass the object I want into the ViewModel everytime. Any suggestions, better approach is greatly appreciated.

Developer
Aug 6, 2012 at 10:04 PM

Hi,

The problem seems to be that you are creating two different views (each with its own view model).

Based on my understanding, in the following line you are resolving an instance of the ProductDetailsView by passing the dataItem to the "ProductToOpen" parameter of the view model.

var detailPage = _unityContainer.Resolve<ProductDetailView>(new ParameterOverride("ProductToOpen",
dataItem).OnType<ProductDetailViewModel>());
Then, in the following line, you are performing a navigation request to a ProductDetailsView, which doesn't know the aforementioned view at all. Therefore, the navigation request creates a new ProductDetailsView where a new ProductDetailsViewModel is injected and this new view is added to the region.

_regionManager.RequestNavigate(RegionNames.MainRegion, 
new Uri(typeof(ProductDetailView).FullName, UriKind.Relative));
Based on this, this is why the view injected in your region does not have the dataItem you specified, because they are two different views.

In this case I believe the simpler approach to achieve the scenario you are mentioning is to use the view injection instead of navigation, as view injection allows you to inject a specific instance of a view, allowing you to have more control over the composition of the UI.

var detailPage = _unityContainer.Resolve<ProductDetailView>(new ParameterOverride("ProductToOpen",
dataItem).OnType<ProductDetailViewModel>());
_regionManager.Regions[RegionNames.MainRegion].Add(detailPage);

I hope you find this useful,

Damian Cherubini
http://blogs.southworks.net/dcherubini

Aug 7, 2012 at 2:11 AM

Thanks for your reply; I follow what you are saying, but I am using Non-Linear navigation and I need the navigation framework methods to be called.  When I tried this code, after adding the view, how can I navigate to it.  I do not naivgate to it.

You mentioned simpler approach which is what you showed, but what are my options if I want use requestnavigate and still use parameteroverride?

 

 

Developer
Aug 7, 2012 at 2:49 PM
Edited Aug 7, 2012 at 2:49 PM

Hi,

Based on my understanding, once you added the instance of your view to your region like Damian's mentioned by using view injection approach, you could navigate to it, by using the view's type Name or FullName without problems, for example like this:

_regionManager.RequestNavigate(RegionNames.MainRegion, new Uri(typeof(ProductDetailView).Fullname, UriKind.Relative));

This is because to find the target of the navigation request the RegionNavigationContentLoader first calls the GetCandidatesFromRegion method, which returns the set of candidates by comparing the requested contract name with the type Name or FullName of the views present in the region. And if no candidates are found then a new instance is retrieved from the container using the target contract name, which as mentioned before won't be the same instance resolved when using the ParameterOverride.

As far as I know this would be the recommended approach, based on the aforementioned behavior.

I hope you find this useful,

Agustin Adami
http://blogs.southworks.net/aadami