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