Windows Phone Mini-Tutorial
In the third part of the MVVM Light Toolkit Soup To Nuts (part 1 is here) I started with an application that had two pages, and a button on the first that was to cause a navigation to the second page. You can download the starting source code here.
In that article I explained how the VM cannot call the Navigate service, but that you could use messaging to have the View make the call. While that is correct, there is an easier way; which is to grab the rootFrame and to call Navigate on that.
To do this, open the starting application and navigate to the GoToPage2() method that is called by the relay command. Remove the MessageBox and instead add this line to obtain the RootFrame of the current application,
var rootFrame = (App.Current as App).RootFrame;
Once you have that in hand, you can call the navigation service directly from the View Model,
rootFrame.Navigate( new System.Uri( "/Views/Page2.xaml", System.UriKind.Relative ));
This greatly simplifies the code and avoids the added complexity of using messaging back to the original page to perform the navigation.
This appears to be the last article in the series. Here are all that I found:
http://jesseliberty.com/2011/01/04/wpfs-mvvm-light-toolkit-soup-to-nuts-part-i/
http://jesseliberty.com/2011/01/05/windows-phone-from-scratch-mvvm-light-toolkit-soup-to-nuts-part-2/
http://jesseliberty.com/2011/01/06/windows-phone-from-scratch%E2%80%93mvvm-light-toolkit-soup-to-nuts-3/
http://jesseliberty.com/2011/01/07/windows-phone-from-scratch-19-mvvm-light-toolkit-soup-to-nuts-4/
http://jesseliberty.com/2011/01/09/passing-parameters-with-behaviors-in-mvvm-light-for-windows-phone/
http://jesseliberty.com/2012/01/17/calling-navigate-from-the-view-model/
Accessing a global navigator outside the view model is a violation. If the view model contains functions which require navigation (such as a PageFunction to retrieve something) then the NavigationService to be used must be passed in. Navigation to other unrelated pages should be done from just the view.
This can’t be called MVVM. Why reference views in the view models? It is wrong!
You should write a service that takes care of this that you can mock (or write a test implementation) to make sure that the VM behaves like it should. I think it is wrong to post blogs like this because everyone believes this is the correct approach…
From my understanding and use of the MVVMLight toolkit, VMs are not referencing Views at all, but merely sending messages that a View might listen for and act on.
A global navigator object sounds just as bad, either way you are accessing a global.
My view-model accepts an INavigator object as its constructor. For testing I pass in a SimpleNavigator. For the real app I use a “PhoneApplicationFrameNavigator”, which is just a simple wrapper around a PhoneApplicationFrame.
The code is in the Granite project on Codeplex. Look for “Granite Xaml” library.
Yes guys, it worth but if you have application only with a few pages it’s not a problem to use this approach…
Doesn’t that kill unit-testability? I really prefer having a global navigator object that I can use to handle navigation messages.
I prefer to use a NavigationMap because otherwise you’d be forced to check all the Uri’s scattered though out the application when you change the folders and/or names of the views.
Hi Erno,
Would you be so kind and post an example of such a NavigationMap? I’d be interested in your way of implementation.
Thanks a lot!