WinRT: MVVM Navigation and a MVVM Example App
Until we get the great frameworks like Caliburn.Micro up-to-date with WinRT, one possible solution for doing navigation when using MVVM pattern is to wrap the Frame-object. Here’s a simple implementation (which could be further enhanced by extracting an interface from it):
public class NavigationService { readonly Frame frame; public NavigationService(Frame frame) { this.frame = frame; } public void GoBack() { frame.GoBack(); } public void GoForward() { frame.GoForward(); } public bool Navigate<T>(object parameter = null) { var type = typeof(T); return Navigate(type, parameter); } public bool Navigate(Type source, object parameter = null) { return frame.Navigate(source, parameter); } }
The NavigationService can be initialized by passing in the root frame, for example in the App.xaml.cs where the root frame is created:
// Create a Frame to act navigation context and navigate to the first page var rootFrame = new Frame(); App.NavigationService = new NavigationService(rootFrame); rootFrame.Navigate(typeof(BlankPage));
If you’re using some container to create your view models, the NavigationService-instance can be registered into it as a singleton. If you’re using a simple ViewModelLocator without a container, the NavigationService can be added as a property to the App-class and it can be accessed when creating the view models. In either case, the NavigationService should be passed to the VM through the constructor, after which navigation from a view model is a straightforward task.
Here’s an example of a view model which uses the NavigationService to navigate forward to a new page:
public class BlankPageViewModel { private readonly NavigationService navigation; public BlankPageViewModel(NavigationService navigation) { this.navigation = navigation; } public DelegateCommand GoToNextPage { get { return new DelegateCommand(x => navigation.Navigate<SecondPage>(), x => true); } } }
The BlankPageViewModel is constructed inside the ViewModelLocator-class:
public BlankPageViewModel BlankPageViewModel { get { return new BlankPageViewModel(App.NavigationService); } }
A sample app containing two pages and the NavigationService-wrapper can be found from GitHub. The sample app also shows a basic implementation of the view model locator.