My NavigationService for UWP apps
For a change, an article in English due to audience on this topic. Recently, I read about NavigationService in “MVVM Light” version 5 and I was surprised to see the usage of code-behind with NavigateTo event to collect data.
I propose here a very simple solution which works without the need of code-behind.
My own implementation of NavigationService is the following
public class NavigationService : INavigationService, IDisposable { #if WINDOWS_PHONE_APP public NavigationService() { Windows.Phone.UI.Input.HardwareButtons.BackPressed += HardwareButtons_BackPressed; } private void HardwareButtons_BackPressed(object sender, Windows.Phone.UI.Input.BackPressedEventArgs e) { if(CanGoBack()) { GoBack(); e.Handled = true; } } #endif private readonly Dictionary<String, Type> _framesDictionary = new Dictionary<string, Type>(); public object CurrentData { get; set; } public void RegisterPage(string key, Type type) { _framesDictionary.Add(key, type); } public void NavigateTo(string key) { var currentFrame = Window.Current.Content as Frame; var nextFrameType = _framesDictionary[key]; if (currentFrame != null) { CurrentData = null; currentFrame.Navigate(nextFrameType); } } public void NavigateTo(string key, object data) { var currentFrame = Window.Current.Content as Frame; var nextFrameType = _framesDictionary[key]; if (currentFrame != null) { CurrentData = data; currentFrame.Navigate(nextFrameType); } } public bool CanGoBack() { var currentFrame = Window.Current.Content as Frame; return currentFrame != null && currentFrame.CanGoBack; } public void GoBack() { if (!CanGoBack()) return; var frame = Window.Current.Content as Frame; if (frame != null) frame.GoBack(); } public void Dispose() { #if WINDOWS_PHONE_APP Windows.Phone.UI.Input.HardwareButtons.BackPressed -= HardwareButtons_BackPressed; #endif } }
First, I use a dictionary of page types to register all the pages of the application. I declare this in the ViewModelLocator.
SimpleIoc.Default.Register<Service.INavigationService>(() => { var navigationService = new NavigationService(); navigationService.RegisterPage("Person", typeof(PersonPage)); return navigationService; });
Secondly, I create a public property named CurrentData used to pass the data through the differents ViewModels.
That’s it, the usage is very simple. In the MainViewModel, I call NavigateTo method of my service with an selected item and the key in order to go to the right page.
SelectedPersonCommand = new RelayCommand<Person>((p) => _navigationService.NavigateTo("Person", p));
And in the details ViewModel, I use the Loaded event to get the data.
LoadedCommand = new RelayCommand(() => { if (_navigationService.CurrentData == null) NewPerson(); else CurrentPerson = _navigationService.CurrentData as Person; });
Leave a Reply