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;
            });
December 28, 2016

Tags: ,

Leave a Reply

Your email address will not be published. Required fields are marked *