How-To: Use a NavigationView to Switch Views
Choosing the right control for your navigation needs is important, and one common choice is NavigationView. This control adapts to different screen sizes and offers a uniform top-level navigation experience. NavigationView is a great option for adaptive, customizable, and mobile-friendly navigation. The Uno Platform extensions for navigation provide built-in support for using NavigationView and NavigationViewItem to switch between views. This tutorial will show you how to configure a NavigationView for use with the navigation extensions.
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. Add XAML namespace mapping
Add the following namespace mapping to the root element of your XAML page:
xmlns:uen="using:Uno.Extensions.Navigation.UI"
2. Define the view's layout
Add a
Gridelement to the root of your XAML page. This will be the container for theNavigationViewand the content area.<Grid> ... </Grid>Add a
NavigationViewcontrol to theGrid. This will be the menu for the app.<NavigationView> ... </NavigationView>Add a
Gridelement to the control.NavigationViewcontains two sections for content:- A pane which contains a list of navigation
MenuItems - The content area intended to correspond with the selected
NavigationViewItem.
For this tutorial,
Gridshould be placed in theContentarea.<Grid> ... </Grid>- A pane which contains a list of navigation
3. Add the navigation view items
Add the
NavigationView.MenuItemscollection to theNavigationViewand add aNavigationViewItemfor each view you want to navigate to.<NavigationView.MenuItems> <NavigationViewItem Content="One" /> <NavigationViewItem Content="Two" /> <NavigationViewItem Content="Three" /> </NavigationView.MenuItems>
4. Add the navigation view content
Inside the
Gridelement of theNavigationView, add aGridelement to represent the content of each view you can to navigate to.<Grid> <Grid> <TextBlock Text="One" FontSize="24" HorizontalAlignment="Center" VerticalAlignment="Center" /> </Grid> <Grid> <TextBlock Text="Two" FontSize="24" HorizontalAlignment="Center" VerticalAlignment="Center" /> </Grid> <Grid> <TextBlock Text="Three" FontSize="24" HorizontalAlignment="Center" VerticalAlignment="Center" /> </Grid> </Grid>
5. Set up navigation
Components with navigation enabled will have their visual trees considered by the navigation service when a request is made. The matching region will be shown and the rest will be hidden.
Add the
uen:Region.Attachedattached property to each of the following elements:- The
Gridelement that contains theNavigationView. - The
NavigationViewelement. - The
Gridelement that contains the content area.
uen:Region.Attached="True"- The
Setting this to
Truewill enable the navigation extensions for the element.Add the
uen:Region.Nameattached property to each of theNavigationViewItemelements. This will define the name of the view that theNavigationViewItemwill navigate to.uen:Region.Name="One"The full code for the
NavigationViewItemelements should look like the code example below:<NavigationView.MenuItems> <NavigationViewItem Content="One" uen:Region.Name="One" /> ... </NavigationView.MenuItems>Add the
uen:Region.Navigatorattached property to theGridelement that contains the content area. This will set the type of navigation to adjust the visibility of the content area's children.uen:Region.Navigator="Visibility"Important
Even if you're not utilizing the
<Grid>element to arrange the content (ie, you're navigating between pages defined with routes), you must still include the<Grid>element with theuen:Region.Navigator="Visibility"anduen:Region.Attached="True"attached properties. These properties are essential for enabling the navigator functionality.Add the
uen:Region.Nameattached property to each of theGridelements that contain the content area. This will define the name of the view that theGridwill represent.uen:Region.Name="One"The full code for the
Gridelements should look like the code example below:<Grid uen:Region.Name="One" Visibility="Collapsed"> <TextBlock Text="One" FontSize="24" HorizontalAlignment="Center" VerticalAlignment="Center" /> </Grid> <Grid uen:Region.Name="Two" Visibility="Collapsed"> <TextBlock Text="Two" FontSize="24" HorizontalAlignment="Center" VerticalAlignment="Center" /> </Grid> <Grid uen:Region.Name="Three" Visibility="Collapsed"> <TextBlock Text="Three" FontSize="24" HorizontalAlignment="Center" VerticalAlignment="Center" /> </Grid>Set the
Visibilityof theGridelements toCollapsedto hide the content area's children beforehand:Visibility="Collapsed"
Navigating to Page elements
You may want to navigate to a
Pageview element represented by a route name. It is possible to do this without defining the view element alongside the other content areas. For instance, you may need to display a products pageProductsPagewhich will be defined in a separate XAML file.Add a new Page item to your app called
ProductsPagewith the following code:<Page x:Class="UsingNavigationView.Views.ProductsPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:Uno.Extensions.Navigation.UI.Samples" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <Grid> <TextBlock Text="Products" FontSize="24" HorizontalAlignment="Center" VerticalAlignment="Center" /> </Grid> </Page>For the purposes for this tutorial,
ProductsPagewill be associated with its own view modelProductsViewModel. Add a new Class item to your app calledProductsViewModelwith the following code:namespace UsingNavigationView.ViewModels; public class ProductsViewModel { public ProductsViewModel() { } }Register
ViewMapandRouteMapinstances inside theRegisterRoutesmethod inApp.xaml.cs. This associates theProductsPagedescribed above withProductsViewModel, 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<ProductsPage, ProductsViewModel>(), new ViewMap<MainPage, MainViewModel>() ); routes.Register( new RouteMap("", View: views.FindByViewModel<ShellViewModel>(), Nested: [ new RouteMap("Main", View: views.FindByViewModel<MainViewModel>(), Nested: [ new RouteMap("Products", View: views.FindByViewModel<ProductsViewModel>()) ] ) ] ) ); }Note
To ensure selecting a
NavigationViewItemonly updates the content region (and doesn’t replace the entire page or theNavigationViewitself), nest eachNavigationViewItemas aRouteMapunder theMainRouteMap. You do not need to declare explicitRouteMapentries for navigation to work, but if you do, they must be nested under Main.Importantly, the snippet above establishes a route name
ProductsforProductsPage. We can use this route name to navigate to theProductsPageview element.Add a
NavigationViewItemto theNavigationViewelement with theuen:Region.Nameattached property set toProducts.<NavigationView.MenuItems> <NavigationViewItem Content="One" uen:Region.Name="One" /> <NavigationViewItem Content="Two" uen:Region.Name="Two" /> <NavigationViewItem Content="Three" uen:Region.Name="Three" /> <!-- Adds a products item --> <NavigationViewItem Content="Products" uen:Region.Name="Products" /> </NavigationView.MenuItems>
Using the Navigation.Data attached property
Sometimes, it is necessary to send data to your ViewModel from the previous page. This can be done using the Navigation.Data attached property. For example, if you want to send an Entity object from the MainViewModel to the ProductsViewModel:
<!-- Adds a products item -->
<NavigationViewItem Content="Products"
+ uen:Navigation.Data="{Binding Entity}"
uen:Region.Name="Products" />
For the full setup and more information on using the Navigation.Data attached property, refer to the documentation in the How-To: Navigate in XAML guide.
Note
You also need to set up a DataViewMap. For more information on ViewMap and DataViewMap, refer to the ViewMap documentation in the How-To: Define Routes guide.
6. Putting it all together
Observe how the
NavigationViewand the content area are now connected. When you select aNavigationViewItem, the correspondingGridorPagewill be shown.If the route name specified represents a
Pageelement, aFramewill be created upon navigation to host thePageelement. ThisFramewill be added to the visual tree in order to support subsequent navigation to otherPageelements.Because the navigation service maintains an instance of the view, users can leave this new
ProductsPageto view item details and return to it without losing any state such as a product filter they have already specified.Now, you have written a UI layout capable of navigating to views with
NavigationView. Your completedMainPage.xamlshould look like the code example below.
Code example
<Page x:Class="UsingNavigationView.Views.MainPage"
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"
mc:Ignorable="d"
xmlns:uen="using:Uno.Extensions.Navigation.UI"
Background="{ThemeResource MaterialBackgroundBrush}">
<Grid uen:Region.Attached="True">
<NavigationView uen:Region.Attached="true">
<NavigationView.MenuItems>
<NavigationViewItem Content="One"
uen:Region.Name="One" />
<NavigationViewItem Content="Two"
uen:Region.Name="Two" />
<NavigationViewItem Content="Three"
uen:Region.Name="Three" />
<NavigationViewItem Content="Products"
uen:Navigation.Data="{Binding Entity}"
uen:Region.Name="Products" />
</NavigationView.MenuItems>
<Grid uen:Region.Attached="True"
uen:Region.Navigator="Visibility">
<Grid uen:Region.Name="One"
Visibility="Collapsed">
<TextBlock Text="One"
FontSize="24"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Grid>
<Grid uen:Region.Name="Two"
Visibility="Collapsed">
<TextBlock Text="Two"
FontSize="24"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Grid>
<Grid uen:Region.Name="Three"
Visibility="Collapsed">
<TextBlock Text="Three"
FontSize="24"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Grid>
</Grid>
</NavigationView>
</Grid>
</Page>