Prism 4.2 and passing parameter objects and navigationcontentloader

Topics: Prism v4 - WPF 4
Jan 27, 2014 at 3:19 PM
Word of warning up front. I haven't actually ran the 4.2 build I was just looking at the code to see how passing the parameter objects would work. So maybe I'm wrong on my assumptions of what the code is doing.

With that out of the way it seems that Prism will be overriding the object stored in the region.Context with the navigation parameters. From the NavigationWithParametersExtensions.RequestNavigate method.

Right now we use the region.Context as kind of like a viewbag to store data we want views to share. This would break that.

For a different way you can check this http://stackoverflow.com/a/20170410/1798889. It is my code and only works with Unity but there is a UnityRegionNavigationContentLoader so it's not unheard of to do specific Unity implementations. I've refactor the code and would be willing to contribute the latest code.

As far as the UnityRegionNavigationContentLoader I've implemented almost the exact same code in Prism 4 but I ended up having to cache the results because Unity Registrations enumeration will recreate the registrations each time, making multiple calls very slow. The first call we query unity registration and get a list of everything that is register to typeof object and then just that list instead of querying the registration because of performance.
Coordinator
Jan 28, 2014 at 8:05 PM
We are looking into this issue and ways to ensure that we do not break your app. Our next drop should address this issue. The next drop will come in 2 or less weeks.

Thanks for the feedback.
Jan 30, 2014 at 5:58 PM
Thank you. Not to be pushy but I think a lot of people would enjoy to have dependency injection overrides in their application. I know it solved a lot of problems with our application. It's easier than trying to store stuff in navigation events and retrieve them later.
Coordinator
Jan 30, 2014 at 7:26 PM
Hi CharlesNRice,

What do you mean by dependency injection override? Do you mean that you want an abstraction to the container to be passed into your ViewModel so that you can push state into the container to be pulled out by other ViewModels?

-Francis
Jan 30, 2014 at 8:36 PM
We use lots of interfaces and constructor injection in our application. We have default implementations of the interfaces registered with Unity and for the most part unity will fill the constructor dependency with the objects based on their lifetime.

One example we have is a MessageBoxView that takes in it's constructor a IMessageBoxViewModel.
public interface IMessageBoxViewModel
{
    string[] Choices { get; set; }
    string Title { get; set; }
    string Content { get; set; }
}

public MessageBoxViewModel : IMessageBoxViewModel
{
        public MessageBoxViewModel()
        {
            //default choices
            Content = "Continue?";
            Choices = new [] {"Ok","Cancel"};
        }

       public string[] Choices { get; set; }
       public string Title { get; set; }
       public string Content { get; set; }
}
If I use the RequestNavigate and pass in the Uri to the MessageBox I'm going to get a messagebox with Ok & Cancel with the content saying "Continue?". Because unity will resolve a new messageboxviewmodel.

But if I want to change the messageboxviewmodel to a different message I can do this.
   // Technically I use unity to resolve messageboxviewmodel but it doesn't matter for this exercise. 
   IMessageBoxViewModel messageBoxViewModel = new MessageBoxViewModel();
   messageBoxViewModel.Content = "Save changes?";
   messageBoxViewModel.Choices = new [] {"Yes", "No", "Cancel"};
From the code from stackoverflow link I sent I can do
   var navUri = new NavigationUri("MessageBoxView");
   navUri.Add(messageBoxViewModel );
   RequestNavigate("Popup", navUri);
This will create a new MessageBoxView but instead of creating a new MessageBoxViewModel unity will inject the messageBoxViewModel object I created.

Using this I can do dependency overrides when needed or if we have interfaces in the constructor to swap out implementations depending on the application state.

Also with Unity you can send in overrides and if the object graph doesn't need them they are just ignored. So in the CreateNewRegionItem of the RegionNavigationContentLoader we always pass in the UriQuery. If one of our classes need it we can just add it to the constructor and get access to it. That's not part of the stackoverflow post. I added that in later.

This allows for us to pass information to the viewmodels or views. It doesn't have to replace the entire viewmodel it would be whatever in the unity object graph that unity would be newing up when resolving a view..