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 a reference to Uno.Extensions.Navigation.Toolkit.WinUI nuget package and that you call the UseToolkitNavigation extension method on the IApplicationBuilder (not IHostBuilder).
var builder = this.CreateBuilder(args)
// Add navigation support for toolkit controls such as TabBar and NavigationView
.UseToolkitNavigation()
.Configure(host => host....);
Step-by-steps
1. Add necessary XAML namespaces
Update the
Pageelement inMainPage.xamlto 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
RowDefinitions to the rootGridinMainPage.xaml:<Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition /> </Grid.RowDefinitions> </Grid>Define initial page and
TabBarItemcontent. It's important to make each element that represents a sector of app content have it'sVisibilityexplicitly set toCollapsed. Uno.Extensions will handle toggling it back toVisiblewhen 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
TabBarto 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
TabBarcontrolThe containing element of the collapsed content
GriddefinitionsThe 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.Nameattached 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
Visibilityusing theRegion.Navigatorattached property on the containing element of your collapsed contentGriddefinitions:<Grid uen:Region.Attached="True" uen:Region.Navigator="Visibility" Grid.Row="1">
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 a view element alongside the other content regions. For instance, you may need to display a subscription sign up pageSignUpPagewhich will be defined in a separate XAML file.Add a new Page item to your app called
SignUpPagewith 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,
SignUpPagewill be associated with its own view modelSignUpViewModel. Add a new Class item to your app calledSignUpViewModelwith the following code:namespace UsingTabBar.ViewModels; public class SignUpViewModel { public SignUpViewMode() { } }Register
ViewMapandRouteMapinstances inside theRegisterRoutesmethod inApp.cs. This associates theSignUpPagedescribed 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<ShellControl, ShellViewModel>(), new ViewMap<LoginPage, LoginViewModel>(), new ViewMap<MainPage, MainViewModel>() ); routes.Register( new RouteMap("", View: views.FindByViewModel<ShellViewModel>(), Nested: new RouteMap[] { new RouteMap("Main", View: views.FindByViewModel<MainViewModel>(), Nested: new RouteMap[] { new RouteMap("Login", View: views.FindByViewModel<LoginViewModel>()) }) })); }Importantly, the snippet above establishes a route name
SignUpforSignUpPage. We can use this route name to navigate to theSignUpPageview element.Add a
TabBarItemto theTabBarelement with theuen:Region.Nameattached 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
TabBarItemis selected, the content which corresponds to the route name of the item will be displayed, with theVisibilityproperty changed if needed.If that route name 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
SignUpPageand 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.xamlshould 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>