How to share an app bar across pages (XAML)

Applies to Windows and Windows Phone

Each Page in a Windows Runtime app can have an AppBar assigned to its TopAppBar and BottomAppBar properties. But you might want to use the same AppBar across related pages in your app to provide common navigation or commands. For example, you might provide a navigation bar at the top of your app that lets a user navigate between pages. You want to show the same navigation bar for every page instead of re-creating it in each page.

Here, we demonstrate some ways you can share an AppBar or CommandBar across pages. This tutorial is based on the Flat navigation, start to finish topic and the associated Flat navigation sample. See the Flat navigation sample for the full code.

Roadmap: How does this topic relate to others? See:

What you need to know

Technologies

Prerequisites

Instructions

Add a shared app bar to a page

To add a common app bar to more than one page, create a new class that is derived from the Page class. In this tutorial, you create a class called NavigationPage. It inherits the TopAppBar and BottomAppBar properties from the Page class. You add navigation commands to the top app bar, and other shared commands to the bottom app bar. Then, you change the app pages to derive from NavigationPage instead of Page, so each page inherits the commands you defined.

JJ150604.wedge(en-us,WIN.10).gifTo add a shared AppBar

  1. Create a new class derived from the Page class. For this tutorial, name the class NavigationPage.

    See NavigationPage.cs in the complete code at the end of this tutorial.

    
    public class NavigationPage : Page
    {
        public NavigationPage()
        {
    
        }
    }
    
    
    
  2. Assign an AppBar control with navigation commands to the TopAppBar property of the NavigationPage class. The AppBar content is a UserControl that you define in the next step.
    
    public class NavigationPage : Page
    {
        public NavigationPage()
        {
            Loaded += NavigationPage_Loaded;
        }
    
        void NavigationPage_Loaded(object sender, Windows.UI.Xaml.RoutedEventArgs e)
        {
            // Navigation controls go in the top app bar.
            AppBar navBar = new AppBar();
            navBar.Background = new SolidColorBrush(new Color() { A=255, R = 0, G = 178, B = 240 }); 
            navBar.Content = new NavigationControl();
            this.TopAppBar = navBar;
        }
    }
    
    
    
  3. Because an AppBar control can contain any content, you can put all the navigation commands together in a UserControl, and set the UserControl as the content of the AppBar. For this tutorial, name the UserControl NavigationControl.
    
    <UserControl
        x:Class="FlatNavTemplate.NavigationControl"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:FlatNavTemplate"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        d:DesignHeight="300"
        d:DesignWidth="400">
        <UserControl.Resources>
            <Style TargetType="Button">
                <Setter Property="Width" Value="140"/>
                <Setter Property="Height" Value="60"/>
                <Setter Property="Margin" Value="5"/>
            </Style>
        </UserControl.Resources>
    
       <StackPanel Orientation="Horizontal">
            <Button x:Uid="appbarHome" Click="NavButton_Click" Tag="FlatNavTemplate.Pages.HomePage"/>
            <Button x:Uid="appbarPage2" Click="NavButton_Click" Tag="FlatNavTemplate.Pages.Page2"/>
            <!-- Add more buttons here as needed for new pages. -->
            <!-- Assign the fully qualified page name to the button's Tag property. -->
        </StackPanel>
    </UserControl>
    
    
  4. In the code page of the UserControl (NavigationControl.xaml.cs), add code to navigate between pages.

    Here, you use the Tag property of each navigation button to specify the name of the page to navigate to.

    
    public sealed partial class NavigationControl : UserControl
    {
        public NavigationControl()
        {
            this.InitializeComponent();
        }
    
        private void NavButton_Click(object sender, RoutedEventArgs e)
        {
            Button b = sender as Button;
            Frame rootFrame = Window.Current.Content as Frame;
    
            if (b != null && b.Tag != null)
            {
                Type pageType = Type.GetType(b.Tag.ToString());
    
                // Make sure the page type exists, but don't navigate to it if it's already the current page.
                if (pageType != null && rootFrame.CurrentSourcePageType != pageType)
                {
                    (App.Current as App).Navigate(pageType);
                }
                else if (pageType == null)
                {
                    // TODO: Optional - Do something if page not found.
                }
            }
        }
    }
    
    

Add a shared CommandBar to a page

Windows 8.1:  CommandBar and AppBarButton controls are available only in Windows 8.1 and Windows Phone 8.1. For Windows 8, use AppBar and Button.

JJ150604.wedge(en-us,WIN.10).gifTo add a shared CommandBar

  • Add a CommandBar to the BottomAppBar property of the NavigationPage class.

    Because the CommandBar can only have AppBarButton controls as its content, you can’t put your commands in a UserControl as you did for the AppBar. Instead, add the commands in code. In this tutorial, you add a Help button on the CommandBar that's shared across all pages. You can see the Help button Click event handler in the complete code at the end of this tutorial. See Quickstart: Add app help for more info.

    Tip  

    You can add commands for a specific page when the user navigates to that page, and remove them when they navigate away. See How to add contextual commands to an app bar for more info.

    
    public class NavigationPage : Page
    {
        public NavigationPage()
        {
            Loaded += NavigationPage_Loaded;
        }
    
        void NavigationPage_Loaded(object sender, Windows.UI.Xaml.RoutedEventArgs e)
        {
            // CommandBar for Help command goes in the BottomAppBar.
            CommandBar commandBar = new CommandBar();
            commandBar.Background = new SolidColorBrush(new Color() { A = 255, R = 0, G = 178, B = 240 });
                
            // Create the Help button.
            AppBarButton helpButton = new AppBarButton();
            helpButton.Icon = new SymbolIcon(Symbol.Help);
            helpButton.Label = "Help";
            helpButton.Click += helpButton_Click;
                
            // Add the Help button to the command bar.
            commandBar.PrimaryCommands.Add(helpButton);
            this.BottomAppBar = commandBar;
        }
    }
    
    
    

Add pages to your app

  1. Add app pages between which the user can navigate.

    See HomePage.xaml and Page2.xaml in the complete code at the end of this tutorial.

  2. Change the app pages to derive from NavigationPage instead of from Page. Each NavigationPage derived page has the navigation and help commands you defined.

    Here's the definition of HomePage updated to derive from NavigationPage.

    
    
    <nav:NavigationPage
        x:Name="pageRoot"
        x:Class="FlatNavTemplate.Pages.HomePage"
        DataContext="{Binding DefaultViewModel, RelativeSource={RelativeSource Self}}"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:nav="using:FlatNavTemplate"
        xmlns:local="using:FlatNavTemplate.Pages"
        xmlns:common="using:FlatNavTemplate.Common"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
    
        <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
            <-- PAGE CONTENT -->   
        </Grid>
    </nav:NavigationPage>
    
    
    
    
    public sealed partial class HomePage : NavigationPage
    {
    
    }
    
    

Remarks

Download the Flat navigation sample to see this code in action.

Complete example

NavigationPage


using Windows.UI;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;

namespace FlatNavTemplate
{
    public class NavigationPage : Page
    {
        public static NavigationPage Current;

        public NavigationPage()
        {
            Loaded += NavigationPage_Loaded;
        }

        void NavigationPage_Loaded(object sender, Windows.UI.Xaml.RoutedEventArgs e)
        {
            // To access the app bars from the code of a derived page, 
            // use NavigationPage.Current.TopAppBar or NavigationPage.Current.BottomAppBar.
            Current = this;

            // Navigation controls go in the top app bar.
            AppBar navBar = new AppBar();
            navBar.Background = new SolidColorBrush(new Color() { A=255, R = 0, G = 178, B = 240 });
            navBar.Content = new NavigationControl();
            this.TopAppBar = navBar;

            // CommandBar for Help command goes in the BottomAppBar.
            CommandBar commandBar = new CommandBar();
            commandBar.Background = new SolidColorBrush(new Color() { A = 255, R = 0, G = 178, B = 240 });
            // Create the Help button.
            AppBarButton helpButton = new AppBarButton();
            helpButton.Icon = new SymbolIcon(Symbol.Help);
            helpButton.Label = "Help";
            helpButton.Click += helpButton_Click;
            // Add the Help button to the command bar.
            commandBar.PrimaryCommands.Add(helpButton);
            this.BottomAppBar = commandBar;
        }

        void helpButton_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
        {
            Settings.HelpSettings helpSettingsFlyout = new Settings.HelpSettings();
            // When the settings flyout is opened from the app bar instead of from
            // the setting charm, use the ShowIndependent() method.
            helpSettingsFlyout.ShowIndependent();

            // Close the app bars.
            this.TopAppBar.IsOpen = false;
            this.BottomAppBar.IsOpen = false;
        }
    }
}

NavigationControl


<UserControl
    x:Class="FlatNavTemplate.NavigationControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:FlatNavTemplate"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300"
    d:DesignWidth="400">
    <UserControl.Resources>
        <Style TargetType="Button">
            <Setter Property="Width" Value="140"/>
            <Setter Property="Height" Value="60"/>
            <Setter Property="Margin" Value="5"/>
        </Style>
    </UserControl.Resources>
    
    <StackPanel Orientation="Horizontal">       
        <Button x:Uid="appbarHome" Click="NavButton_Click" Tag="FlatNavTemplate.Pages.HomePage"/>
        <Button x:Uid="appbarPage2" Click="NavButton_Click" Tag="FlatNavTemplate.Pages.Page2"/>
        <!-- Add more buttons here as needed for new pages. -->
        <!-- Assign the fully qualified page name to the button's Tag property. -->
    </StackPanel>
</UserControl>



namespace FlatNavTemplate
{
    public sealed partial class NavigationControl : UserControl
    {
        public NavigationControl()
        {
            this.InitializeComponent();
        }

        private void NavButton_Click(object sender, RoutedEventArgs e)
        {
            Button b = sender as Button;
            Frame rootFrame = Window.Current.Content as Frame;

            if (b != null && b.Tag != null)
            {
                Type pageType = Type.GetType(b.Tag.ToString());

                // Make sure the page type exists, but don't navigate to it if it's already the current page.
                if (pageType != null && rootFrame.CurrentSourcePageType != pageType)
                {
                    (App.Current as App).Navigate(pageType);
                }
                else if (pageType == null)
                {
                    // TODO: Optional - Do something if page not found.
                }
            }
        }
    }
}

HomePage


<nav:NavigationPage
    x:Name="pageRoot"
    x:Class="FlatNavTemplate.Pages.HomePage"
    DataContext="{Binding DefaultViewModel, RelativeSource={RelativeSource Self}}"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:nav="using:FlatNavTemplate"
    xmlns:local="using:FlatNavTemplate.Pages"
    xmlns:common="using:FlatNavTemplate.Common"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Page.Resources>
        <!-- TODO: Delete this line if the key AppName is declared in App.xaml -->
        <x:String x:Key="AppName">My Application</x:String>
    </Page.Resources>

    <!--
        This grid acts as a root panel for the page that defines two rows:
        * Row 0 contains the back button and page title
        * Row 1 contains the rest of the page layout
    -->
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid.ChildrenTransitions>
            <TransitionCollection>
                <EntranceThemeTransition/>
            </TransitionCollection>
        </Grid.ChildrenTransitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="140"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <!-- Back button and page title -->
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="120"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Image x:Name="logoimage" HorizontalAlignment="Center" Height="100" VerticalAlignment="Center" 
                   Width="100" Source="ms-appx:///Assets/square70logo.png" IsHitTestVisible="False"/>
            <TextBlock x:Name="pageTitle" Text="{StaticResource AppName}" 
                       Style="{StaticResource HeaderTextBlockStyle}" Grid.Column="1" 
                       IsHitTestVisible="false" TextWrapping="NoWrap" VerticalAlignment="Bottom" 
                       Margin="0,0,30,40"/>
        </Grid>
    </Grid>
</nav:NavigationPage>


public sealed partial class HomePage : NavigationPage
{
    // Only class definition is shown. Template code is removed for clarity.
}

Page2


<nav:NavigationPage
    x:Name="pageRoot"
    x:Class="FlatNavTemplate.Pages.Page2"
    DataContext="{Binding DefaultViewModel, RelativeSource={RelativeSource Self}}"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:nav="using:FlatNavTemplate"
    xmlns:local="using:FlatNavTemplate.Pages"
    xmlns:common="using:FlatNavTemplate.Common"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Page.Resources>
        <!-- TODO: Delete this line if the key AppName is declared in App.xaml -->
        <x:String x:Key="AppName">My Application Page 2</x:String>
    </Page.Resources>
    
    <!--
        This grid acts as a root panel for the page that defines two rows:
        * Row 0 contains the back button and page title
        * Row 1 contains the rest of the page layout
    -->
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid.ChildrenTransitions>
            <TransitionCollection>
                <EntranceThemeTransition/>
            </TransitionCollection>
        </Grid.ChildrenTransitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="140"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <!-- Back button and page title -->
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="120"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Image x:Name="logoimage" HorizontalAlignment="Center" Height="100" VerticalAlignment="Center" 
                   Width="100" Source="ms-appx:///Assets/square70logo.png" IsHitTestVisible="False"/>
            <TextBlock x:Name="pageTitle" Text="{StaticResource AppName}" 
                       Style="{StaticResource HeaderTextBlockStyle}" Grid.Column="1" 
                        IsHitTestVisible="false" TextWrapping="NoWrap" 
                       VerticalAlignment="Bottom" Margin="0,0,30,40"/>
        </Grid>
    </Grid>
</nav:NavigationPage>


public sealed partial class Page2 : NavigationPage
{
    // Only class definition is shown. Template code is removed for clarity.
}

Related topics

Flat navigation sample
XAML AppBar control sample
Quickstart: Adding app bars
Quickstart: Navigating between pages
Flat navigation, start to finish (XAML)
Navigation design for Windows Store apps
Commanding design for Windows Store apps

 

 

Show:
© 2014 Microsoft