-
Notifications
You must be signed in to change notification settings - Fork 2
WPF: Navigation Manager
All navigation operations such as registering navigation views, regions and requesting to navigate handled by interface INavigationManager
public interface INavigationManager
{
INavigationManager RegisterRegionWithView(string regionName, object viewInstance);
INavigationManager RegisterView<TView>(string viewName);
void RequestNavigate(string regionName, string viewName, Action navigationCallback, INavigationParameters navigationParameters);
}
Register instance of INavigationManageras
as a singleton in the container then register all navigable views (Pages, UserControls etc) in the INavigationManager
.
The sample code shows how to register INavigationManager
and all navigable pages in application entry point class (App.xaml.cs file) and used DryIoc container as a IoC container.
public partial class App : Application
{
// Static singleton instance of DryIoc container.
public static readonly IContainer Container = new Container();
/// <summary>
/// Application entry point.
/// </summary>
/// <param name="e">Args</param>
protected override void OnStartup(StartupEventArgs e)
{
// Register INavigationManager service as a singleton.
// Note: It's important to register as a singelton otherwise you will get different instance of managers.
Container.Register<INavigationManager, NavigationManager>(Reuse.Singleton);
// Resolve singleton instance of the navigation manager from container.
Container.Resolve<INavigationManager>()
.RegisterView<PageA>() // register all navigable pages in the manager.
.RegisterView<PageB>()
.RegisterView<PageC>();
// Resolve MainWindow from container then display main window.
Container.Resolve<MainWindow>().Show();
base.OnStartup(e);
}
}
NOTE: You must provide view name when you register views in
INavigationManager.RegisterView<>
. In above example, explicitly not specified view name because by default name of view type will be used implicitly as a view object name. In case of the above example, view typesPageA
,PageB
andPageC
served as a default view name such that "PageA", "PageB" and "PageC".
Region is view area in which navigation object will be displayed. Region is any type of the view objects such as Page, UserControl. Navigation within a region means that a new view is to be displayed within that region. The view to be displayed is identified via a URI, which, by default, refers to the name of the view to be created. You can programmatically initiate navigation using the RequestNavigate
method defined by the INavigateManager
interface.
First define name of the region then register to navigation manager.
Below sample code demonstrates how to make navigation between pages inside frame object. First of all, we define name of the frame "mainFrame" as a region name then we will register region into navigation manager.
<Window x:Class="AppNavigation.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:AppNavigation"
mc:Ignorable="d"
Title="App with navigation"
Height="450"
Width="800">
<StackPanel>
<Frame x:Name="mainFrame"
NavigationUIVisibility="Hidden"
Height="350">
</Frame>
</StackPanel>
</Window>
Register region into INavigationManager
then call INavigationManager.RequestNavigate
method to navigate between views.
public partial class MainWindow : Window
{
public MainWindow()
{
// Bind view model to DataContext
DataContext = App.Container.Resolve<MainWindowViewModel>();
// Initialize visual components
InitializeComponent();
// Resolve navigation manager from static instance of the container.
var navigationManager = App.Container.Resolve<INavigationManager>();
// Register region with unique name and its view instance.
navigationManager.RegisterRegionWithView("MainRegion", this.mainFrame);
// Navigate to page "PageA" inside region "MainRegion" (frame object)
navigationManager.RequestNavigate("MainRegion", "PageA");
}
}
You can pass parameters to INavigationManager.RequestNavigate
then parameters can be handled in view model where implemented interface INavigationAware
The actual interface INavigationAware
defined as shown below.
/// <summary>
/// Provides a way for objects involved in navigation to be notified of navigation activities.
/// </summary>
public interface INavigationAware
{
/// <summary>
/// Called when the implementer has been navigated to.
/// </summary>
/// <param name="navigationContext">The navigation context.</param>
void OnNavigatedTo(NavigationContext navigationContext);
/// <summary>
/// Called when the implementer is being navigated away from.
/// </summary>
/// <param name="navigationContext">The navigation context.</param>
void OnNavigatedFrom(NavigationContext navigationContext);
}
The sample code shows how to navigation parameters between view models.
// File MainWindowViewModel.cs
public class MainWindowViewModel: BindableBase
{
private readonly INavigationManager _navigationManager;
public MainWindowViewModel(INavigationManager navigationManager)
{
_naviagtionManager = navigationManager; // inject navigation manager
}
public void NavigateToPage()
{
var navigationParameters = new DialogParameters
{
{"paramKey1", "paramValue1"},
{"paramKey2", "paramValue2"},
{"paramKey3", "paramValue3"},
}
// Navigate to "PageA" in region which called "MainRegion" with navigation paramaters.
_naviagtionManager.RequestNavigate("MainRegion", "PageA", navigationParameters);
}
}
// File PageAViewModel.cs
public class PageAViewModel : BindableBase, INavigationAware
{
// Bindable property
private string _pageContent;
public string PageContent
{
get => _pageContent;
set => SetProperty(ref _pageContent, value);
}
// Called when navigated to the current page
public void OnNavigatedTo(NavigationContext navigationContext)
{
PageContent += "\nPage parameters:";
// Tries to get navigation parameter where sent as key "paramKey1"
if (navigationContext.Parameters.TryGetValue("paramKey1", out string paramValue1))
{
PageContent += $"\n{paramValue1}";
}
if (navigationContext.Parameters.TryGetValue("paramKey2", out string paramValue2))
{
PageContent += $"\n{paramValue2}";
}
if (navigationContext.Parameters.TryGetValue("paramKey3", out string paramValue3))
{
PageContent += $"\n{paramValue3}";
}
}
// Called when navigated away from this page
public void OnNavigatedFrom(NavigationContext navigationContext)
{
}
}
Check out sample project where demonstrated all features of the Navigation Manager.