How-To: Navigate Between Pages
This topic covers using Navigation to navigate between two pages using frame-based navigation.
Step-by-steps
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 article for creating an application from the template.
1. Navigating to a New Page
Add a new
Page
to navigate to,SamplePage.xaml
, in the UI (shared) projectIn
MainPage.xaml
replace the existingButton
with the following XAML, which includes a handler for the Click event<Button Content="Go to SamplePage" Click="GoToSamplePageClick" />
In the
GoToSamplePageClick
method, use theNavigator
extension method to get a reference to anINavigator
instance and callNavigateViewAsync
to navigate to theSamplePage
. This will push a new instance of theSamplePage
onto the current Frame, pushing theMainPage
to the back-stack.private void GoToSamplePageClick(object sender, RoutedEventArgs e) { _ = this.Navigator()?.NavigateViewAsync<SamplePage>(this); }
2. Navigating Back to the Previous Page
In
SamplePage.xaml
add aButton
with a handler for theClick
event<Button Content="Go Back" Click="GoBackClick" />
Again, use the
Navigator
extension method to access theINavigator
instance and callNavigateBackAsync
. This will cause the frame to navigate to the previous page on the back-stack and releasing theSamplePage
instance.private void GoBackClick(object sender, RoutedEventArgs e) { _ = this.Navigator()?.NavigateBackAsync(this); }
3. Defining ViewMap and RouteMap
At this point, if you inspect the Output window you'll see a line that says something similar to:
For better performance (avoid reflection), create mapping for for path 'Sample', view 'SamplePage', view model
This warning exists because Navigation uses reflection as a fallback mechanism to associate types and the corresponding navigation route. This can be resolved by specifying a ViewMap
and a RouteMap
for the SamplePage
to eliminate the need for reflection
Update the
RegisterRoutes
method in theApp.xaml.host.cs
fileprivate static void RegisterRoutes(IViewRegistry views, IRouteRegistry routes) { views.Register( new ViewMap<ShellControl,ShellViewModel>(), new ViewMap<MainPage, MainViewModel>(), new ViewMap<SecondPage, SecondViewModel>(), new ViewMap<SamplePage>() ); routes.Register( new RouteMap("", View: views.FindByViewModel<ShellViewModel>() , Nested: new RouteMap[] { new RouteMap("Main", View: views.FindByViewModel<MainViewModel>()), new RouteMap("Second", View: views.FindByViewModel<SecondViewModel>()), new RouteMap("Sample", View: views.FindByView<SamplePage>()), })); }
4. Associating a View Model
By defining a ViewMap
that associates a view with a view model, an instance of the view model can dynamically be created and is subsequently set as the DataContext
on the view that's navigated to.
Create a new class
SampleViewModel
in the ViewModels folder of the class library projectpublic class SampleViewModel { public string Title => "Sample Page"; public SampleViewModel() { } }
Update
ViewMap
inApp.xaml.host.cs
to includeSampleViewModel
new ViewMap<SamplePage, SampleViewModel>()
Add
TextBlock
to theSamplePage.xaml
and data bind to theTitle
property<TextBlock Text="{Binding Title}" />
5. Navigating via View Models
The Navigation code can be moved from the SamplePage.cs
code-behind file to the SampleViewModel
.
Update
SampleViewModel
to take a constructor dependency onINavigator
and add aGoBack
method that will call theNavigateBackAsync
methodprivate readonly INavigator _navigator; public SampleViewModel(INavigator navigator) { _navigator = navigator; } public Task GoBack() { return _navigator.NavigateBackAsync(this); }
In order to use
x:Bind
to invoke theGoBack
method on theSampleViewModel
theSamplePage
needs to expose a property that returns theDataContext
as aSampleViewModel
.public SampleViewModel? ViewModel => DataContext as SampleViewModel; public SamplePage() { this.InitializeComponent(); }
Update the
Button
inSamplePage.xaml
to set theClick
method tox:Bind
to theGoBack
method<Button Content="Go Back (View Model)" Click="{x:Bind ViewModel.GoBack}" />