How-To: Navigate in Code
This topic walks through controlling Navigation from code, either in the code-behind file of a Page or in the corresponding view model. One of the Navigation objectives was a single navigation construct that applies wherever you choose to write your navigation code.
Note
This guide uses predefined code created by the Uno Template using the Recommended preset, however, it uses the MVVM approach for the examples instead of MVUX defined in the Recommended preset.
Step-by-step
Important
This guide assumes you used the template wizard or dotnet new unoapp to create your solution. If not, it is recommended that you follow the Creating an application with Uno.Extensions documentation to create an application from the template.
1. Navigating to a New Page
Navigation can be invoked in the code-behind file of a Page by using the Navigator extension method to get an INavigator instance.
Add a new
Pageto navigate to,SamplePage.xamlIn
MainPage.xamlupdate theButtonto the following XAML, which includes a handler for theClickevent<Button Content="Go to SamplePage" Click="GoToSamplePageClick" />In the
GoToSamplePageClickmethod, use theNavigatorextension method to get a reference to anINavigatorinstance and callNavigateViewAsyncto navigate to theSamplePage. This will push a new instance of theSamplePageonto the current frame, pushing theMainPageto the back-stack.private void GoToSamplePageClick(object sender, RoutedEventArgs e) { _ = this.Navigator()?.NavigateViewAsync<SamplePage>(this); }
2. Navigating Back to the Previous Page
In
SamplePage.xamladd aButtonwith a handler for theClickevent<Button Content="Go Back" Click="GoBackClick" />Again, use the
Navigatorextension method to access theINavigatorinstance and callNavigateBackAsync. This will cause the frame to navigate to the previous page on the back-stack and releasing theSamplePageinstance.private void GoBackClick(object sender, RoutedEventArgs e) { _ = this.Navigator()?.NavigateBackAsync(this); }
3. Navigate to a ViewModel
The NavigateViewAsync method uses the type of the view, i.e. SamplePage, to determine the view to navigate to. By associating a view model with a view, Navigation can be defined based on the type of view model to navigate to. This means that the Navigation logic isn't dependent on the UI layer of the application. The Navigation logic can then be moved into a view model and thus making it easier to test.
Create a new class
SampleViewModelin theViewModelsfolder of the class library projectpublic class SampleViewModel { public SampleViewModel() { } }Add
ViewMapandRouteMapinstances in theRegisterRoutesmethod inApp.xaml.cs. This associates theSampleViewModelwith theSamplePage, as well as avoiding the use of reflection for route discovery.private static void RegisterRoutes(IViewRegistry views, IRouteRegistry routes) { views.Register( new ViewMap(ViewModel: typeof(ShellViewModel)), new ViewMap<MainPage, MainViewModel>(), new DataViewMap<SecondPage, SecondViewModel, Entity>(), new ViewMap<SamplePage, SampleViewModel>() ); routes.Register( new RouteMap("", View: views.FindByViewModel<ShellViewModel>(), Nested: [ new ("Main", View: views.FindByViewModel<MainViewModel>()), new ("Second", View: views.FindByViewModel<SecondViewModel>()), new ("Sample", View: views.FindByViewModel<SampleViewModel>()), ] ) ); }Now that there's an association between
SamplePageandSampleViewModelthe code inMainPage.xaml.cscan be updated to use theNavigateViewModelAsyncmethod.private void GoToSamplePageClick(object sender, RoutedEventArgs e) { _ = this.Navigator()?.NavigateViewModelAsync<SampleViewModel>(this); }
4. View Model Navigation
The logic for navigating back from
SamplePagetoMainPagecan be moved into theSampleViewModel. Add theGoBackmethod toSampleViewModelthat uses theINavigatorinstance that's injected via the constructor.public SampleViewModel(INavigator navigator) { _navigator = navigator; } public Task GoBack() { return _navigator.NavigateBackAsync(this); } private readonly INavigator _navigator;During Navigation from
MainPagetoSamplePagean instance of theSampleViewModelwill get created and assigned as theDataContextof the newly createdSamplePage. In order tox:Bindto properties and methods on theSampleViewModel, expose aViewModelproperty that returns theDataContextproperty as aSampleViewModel.public SampleViewModel? ViewModel => DataContext as SampleViewModel; public SamplePage() { this.InitializeComponent(); }Update the
ButtoninSamplePage.xamlto usex:Bindto define the event handler for theClickevent.<Button Content="Go Back (View Model)" Click="{x:Bind ViewModel.GoBack}" />
Tip
The logic to navigate from MainPage to SamplePage can also be refactored into the MainViewModel. Irrespective of whether the logic is in the code-behind or in the view model, it would use the same NavigateViewModelAsync<SampleViewModel> method call.
There are many other extension methods on the INavigator interface that can be used from either the code-behind or view model. Here are a few of the key navigation methods:
NavigateRouteAsync - Navigates to a route specified as a string
NavigateViewAsync - Navigates to a route that matches the view type specified
NavigateViewModelAsync - Navigates to a route that matches the view model type specified
NavigateDataAsync - Navigates to a route that is registered for the data type specified
NavigateForResultAsync - Navigates to a route that is registered to return the result data type specified