How-To: Use a TabBar to Switch Views
The navigation capabilities offered by Uno.Extensions include regions. Regions allow you to associate a specific sector of the view with an individual item on a navigation control from the same Page
. Likewise, the Uno.Extensions library has built-in support for responding to navigation gestures from the Toolkit TabBar
. Follow the steps below to define a user interface centered around navigating with this control.
Since TabBar
comes from the Uno.Toolkit
you need to make sure your project has Toolkit
added to the <UnoFeatures>
property in the Class Library (.csproj) file and that you call the UseToolkitNavigation
extension method on the IApplicationBuilder
(not IHostBuilder
). For more information about UnoFeatures
refer to our Using the Uno.Sdk docs.
var builder = this.CreateBuilder(args)
// Add navigation support for toolkit controls such as TabBar and NavigationView
.UseToolkitNavigation()
.Configure(host => host....);
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 necessary XAML namespaces
Update the
Page
element inMainPage.xaml
to include XAML namespace mappings for Navigation and Uno Toolkit:<Page x:Class="UsingTabBar.Views.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:UsingTabBar.Views" 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" xmlns:utu="using:Uno.Toolkit.UI" ...
2. Define the view's layout
Add
RowDefinition
s to the rootGrid
inMainPage.xaml
:<Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition /> </Grid.RowDefinitions> </Grid>
Define initial page and
TabBarItem
content. It's important to make each element that represents a sector of app content have it'sVisibility
explicitly set toCollapsed
. Uno.Extensions will handle toggling it back toVisible
when necessary<Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition /> </Grid.RowDefinitions> <utu:NavigationBar Content="Main Page" Style="{StaticResource MaterialNavigationBarStyle}" /> <Grid Grid.Row="1"> <Grid Visibility="Collapsed"> <TextBlock Text="One" FontSize="24" HorizontalAlignment="Center" VerticalAlignment="Center" /> </Grid> <Grid Visibility="Collapsed"> <TextBlock Text="Two" FontSize="24" HorizontalAlignment="Center" VerticalAlignment="Center" /> </Grid> <Grid Visibility="Collapsed"> <TextBlock Text="Three" FontSize="24" HorizontalAlignment="Center" VerticalAlignment="Center" /> </Grid> </Grid> </Grid>
Add
TabBar
to the view:<Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition /> </Grid.RowDefinitions> <utu:NavigationBar Content="Main Page" Style="{StaticResource MaterialNavigationBarStyle}" /> <Grid Grid.Row="1"> <Grid Visibility="Collapsed"> <TextBlock Text="One" FontSize="24" HorizontalAlignment="Center" VerticalAlignment="Center" /> </Grid> <Grid Visibility="Collapsed"> <TextBlock Text="Two" FontSize="24" HorizontalAlignment="Center" VerticalAlignment="Center" /> </Grid> <Grid Visibility="Collapsed"> <TextBlock Text="Three" FontSize="24" HorizontalAlignment="Center" VerticalAlignment="Center" /> </Grid> </Grid> <utu:TabBar Grid.Row="2" VerticalAlignment="Bottom"> <utu:TabBar.Items> <utu:TabBarItem Style="{StaticResource MaterialBottomTabBarItemStyle}" /> <utu:TabBarItem Style="{StaticResource MaterialBottomTabBarItemStyle}" /> <utu:TabBarItem Style="{StaticResource MaterialBottomTabBarItemStyle}" /> </utu:TabBar.Items> </utu:TabBar> </Grid>
3. Set up regions and specify navigator type
Use the
Region.Attached="True"
attached property to enable regions on all of the following:The
TabBar
controlThe containing element of the collapsed content
Grid
definitionsThe parent element of both controls
<Grid uen:Region.Attached="True"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition /> </Grid.RowDefinitions> <utu:NavigationBar Content="Main Page" Style="{StaticResource MaterialNavigationBarStyle}" /> <Grid uen:Region.Attached="True" Grid.Row="1"> <Grid Visibility="Collapsed"> <TextBlock Text="One" FontSize="24" HorizontalAlignment="Center" VerticalAlignment="Center" /> </Grid> <Grid Visibility="Collapsed"> <TextBlock Text="Two" FontSize="24" HorizontalAlignment="Center" VerticalAlignment="Center" /> </Grid> <Grid Visibility="Collapsed"> <TextBlock Text="Three" FontSize="24" HorizontalAlignment="Center" VerticalAlignment="Center" /> </Grid> </Grid> <utu:TabBar Grid.Row="2" uen:Region.Attached="True" VerticalAlignment="Bottom"> <utu:TabBar.Items> <utu:TabBarItem Style="{StaticResource MaterialBottomTabBarItemStyle}" /> <utu:TabBarItem Style="{StaticResource MaterialBottomTabBarItemStyle}" /> <utu:TabBarItem Style="{StaticResource MaterialBottomTabBarItemStyle}" /> </utu:TabBar.Items> </utu:TabBar> </Grid>
Name the regions you defined by using the
Region.Name
attached property on both the content itself and associated navigation control item:<Grid uen:Region.Attached="True"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition /> </Grid.RowDefinitions> <utu:NavigationBar Content="Main Page" Style="{StaticResource MaterialNavigationBarStyle}" /> <Grid uen:Region.Attached="True" Grid.Row="1"> <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> <utu:TabBar Grid.Row="2" uen:Region.Attached="True" VerticalAlignment="Bottom"> <utu:TabBar.Items> <utu:TabBarItem uen:Region.Name="One" Style="{StaticResource MaterialBottomTabBarItemStyle}" /> <utu:TabBarItem uen:Region.Name="Two" Style="{StaticResource MaterialBottomTabBarItemStyle}" /> <utu:TabBarItem uen:Region.Name="Three" Style="{StaticResource MaterialBottomTabBarItemStyle}" /> </utu:TabBar.Items> </utu:TabBar> </Grid>
Specify the navigator type as
Visibility
using theRegion.Navigator
attached property on the containing element of your collapsed contentGrid
definitions:<Grid uen:Region.Attached="True" uen:Region.Navigator="Visibility" Grid.Row="1">
Navigating to Page elements
You may want to navigate to a
Page
view element represented by a route name. It is possible to do this without defining a view element alongside the other content regions. For instance, you may need to display a subscription sign up pageSignUpPage
which will be defined in a separate XAML file.Add a new Page item to your app called
SignUpPage
with the following code:<Page x:Class="UsingTabBar.Views.SignUpPage" 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> <StackPanel Orientation="Vertical"> <TextBlock Text="Benefits of subscribing:" FontSize="24" HorizontalAlignment="Center" VerticalAlignment="Center" /> <Button Content="Sign Up" HorizontalAlignment="Center" VerticalAlignment="Center" /> </StackPanel> </Grid> </Page>
For the purposes for this tutorial,
SignUpPage
will be associated with its own view modelSignUpViewModel
. Add a new Class item to your app calledSignUpViewModel
with the following code:namespace UsingTabBar.ViewModels; public class SignUpViewModel { public SignUpViewMode() { } }
Register
ViewMap
andRouteMap
instances inside theRegisterRoutes
method inApp.cs
. This associates theSignUpPage
described above withSignUpViewModel
, 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<LoginPage, LoginViewModel>(), new ViewMap<MainPage, MainViewModel>() ); routes.Register( new RouteMap("", View: views.FindByViewModel<ShellViewModel>(), Nested: [ new RouteMap("Main", View: views.FindByViewModel<MainViewModel>(), Nested: [ new RouteMap("Login", View: views.FindByViewModel<LoginViewModel>()) ] ) ] ) ); }
Importantly, the snippet above establishes a route name
SignUp
forSignUpPage
. We can use this route name to navigate to theSignUpPage
view element.Add a
TabBarItem
to theTabBar
element with theuen:Region.Name
attached property set toSignUp
.<utu:TabBar.Items> <utu:TabBarItem uen:Region.Name="One" Style="{StaticResource MaterialBottomTabBarItemStyle}" /> <utu:TabBarItem uen:Region.Name="Two" Style="{StaticResource MaterialBottomTabBarItemStyle}" /> <utu:TabBarItem uen:Region.Name="Three" Style="{StaticResource MaterialBottomTabBarItemStyle}" /> <!-- Sign up item --> <utu:TabBarItem uen:Region.Name="SignUp" Style="{StaticResource MaterialBottomTabBarItemStyle}" /> </utu:TabBar.Items>
6. Putting it all together
When a
TabBarItem
is selected, the content which corresponds to the route name of the item will be displayed, with theVisibility
property changed if needed.If that route name represents a
Page
element, aFrame
will be created upon navigation to host thePage
element. ThisFrame
will be added to the visual tree in order to support subsequent navigation to otherPage
elements.Because the navigation service maintains an instance of the view, users can leave this new
SignUpPage
and return to it without losing any state such as form data.Now that you have a functional tab bar navigation system, you can run it to see the results. Your completed
MainPage.xaml
should look like the code example below.
Code example
<Page x:Class="UsingTabBar.Views.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:UsingTabBar.Views"
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"
xmlns:utu="using:Uno.Toolkit.UI">
<Grid uen:Region.Attached="True">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<utu:NavigationBar Content="Main Page"
Style="{StaticResource MaterialNavigationBarStyle}" />
<Grid uen:Region.Attached="True"
uen:Region.Navigator="Visibility"
Grid.Row="1">
<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>
<utu:TabBar Grid.Row="2"
uen:Region.Attached="True"
VerticalAlignment="Bottom">
<utu:TabBar.Items>
<utu:TabBarItem uen:Region.Name="One"
Style="{StaticResource MaterialBottomTabBarItemStyle}" />
<utu:TabBarItem uen:Region.Name="Two"
Style="{StaticResource MaterialBottomTabBarItemStyle}" />
<utu:TabBarItem uen:Region.Name="Three"
Style="{StaticResource MaterialBottomTabBarItemStyle}" />
<utu:TabBarItem uen:Region.Name="SignUp"
Style="{StaticResource MaterialBottomTabBarItemStyle}" />
</utu:TabBar.Items>
</utu:TabBar>
</Grid>
</Page>