Navigating to same viewmodel but with different data and keep navigation stack correct with MVVM Light

Long title, I know… and even with that the scenario I’m trying to describe isn’t clear yet, so let me explain even more.

In my latest app ConcertWall you can open a Venue and look at the concerts that are available, when you open up a Concert you can – again – go through to the same Venue and pick another Concert to get the details.

Now translated to the technical MVVM background this means: Venue viewmodel A > Concert viewmodel A > Venue viewmodel A > Concert viewmodel B > etc…

But when you try to do this in a normal MVVM Light way, you’ll break the Navigation stack! Because when you’ll navigate back from concert viewmodel B to the venue viewmodel A to the concert viewmodel A, you’ll notice A will no longer be visible but you’ll get B again!

This problem is easy to explain, you only retain one instance of the concert viewmodel and if you do nothing when navigating, only the last loaded datacontext will be shown each time you get on the concert view!

Now how can we fix this, there are several ways ( like Nico Vermeir shows one here ), but I like to use the SimpleIoc functionality that is present in MVVM Light and let it handle my instances instead of adding extra in memory containers!

So how do you get this working, first you’ll need to add a special method inside your ViewModelLocator called GetViewModel<T>

This is actually the real solution, all it does is keep track of all separate instances of a given viewmodel based on a key you provide! So no hassle with keeping track of it myself.

Only thing left to do is using this method when navigating to the viewmodel you want to track based on a key ( in our example the Concert viewmodel ).

Best thing to use as key, is the unique identifier that is present in your data model that needs to be shown on that view ( in our example the Concert ID ) and add that to the navigation URI.

Now when you navigate to the view, you can no longer use the MVVM Light datacontext binding in XAML! This because we’ll need to set it our self through use of the above provided GetViewModel method based on the key that is used in the navigation URI. So in the code behind of the given view, override the OnNavigatedTo method and inject the correct viewmodel datacontext!

I’m also calling a RefreshLayout method to refresh the current data on each view load, but depending on the app scenario this is maybe not needed.

With all that in place, you can go forward and call the same viewmodel with different data over and over, and keep your navigation back stack intact because of the added key inside the navigation URI.

Happy coding!

Semantic Zoom with MVVMLight – Windows 8 Metro

This week I’ve been trying out some Windows 8 Metro development and by doing so I came across something I think will help out other devs.
I wanted to try out one of the key new features that is presented in Windows 8, called Semantic Zoom ( read about/view it here ).

But because of the fact I’m mostly familiar with Windows Phone 7 development, I wanted to use Laurent Bugnion’s MVVMLight framework also on Windows 8. You can get a v4Beta1 version here…

So by doing so, I needed to tweak my code so it would fit nicely with the Semantic Zoom pattern. Let me show you how I did this.

First create a new MVVMLight Project

image

Than open the Model folder and add a class called Car.cs

 

And a class called Manufacturer.cs

These 2 classes will define your Group and Items needed for the Semantic Zoom. So for the Zoomed In view we will be presenting all Cars that we have ( grouped by manufacturer ) and in the Zoomed Out view we will show a birds eye overview of all Manufacturers with some general details about the amount of Cars available.

Next thing on our list is adding an ObservableCollection of Manufacturers to the MainViewModel.

Be sure to initiate your data, we will now for this demo do this in the MainViewModel constructor.

 

Now open up your MainPage.xaml and get rid of the following TextBlock

Put following code into place ( where the textblock was previously set ) to get your title and backbutton

So now we need to add our Semantic Zoom control, do this directly underneath the backbutton and page title xaml

 

Before we continue we will be adding a CollectionViewSource, this is needed to fill the Item grid later on in the Semantic Zoom control! You place this inside the MainPage.xaml <ResourceDictionary> tag, it should be there already and contain <ResourceDictionary.MergedDictionaries> tag… Take note that it is actually here that we will be binding to our ObservableCollection froml our MainViewModel!

 

So with this in place we can continue with our ZoomedIn view, all we will be doing is defining visual elements on how we want to structure our data. In our case we will be adding the Manifacturer name as Group header with Car models underneath it, to accomplish this add following xaml inside the <SemanticZoom.ZoomedInView></SemanticZoom.ZoomedInView> tags

 

Now that the ZoomInView is ready, add following xaml for our ZoomOutView. Now we will again show the Manufacturer name but only with a total Car count underneath it so we can get our birds eye overview! Place the code inside the <SemanticZoom.ZoomedOutView></SemanticZoom.ZoomedOutView> tags

 

Before we are done we do actually need to add one line of extra code in the MainPage.xaml.cs file! To get the ZoomedOutView working we need to link the groupGridView with the groupedItemsViewSource

So inside the constructor of the MainPage.xaml.cs add following line underneath the this.InitializeComponent(); call

And that’s it… if everything goes well you should have following result

image

image

The complete solution can be downloaded here… MvvmLight1