Skip to content
/

Responsive Pivot Headers in Universal Windows Platform apps

For a Universal Windows App I wanted to implement a Pivot. Reading the guidelines for tabs and pivots by Microsoft I got inspired by the examples given. However, no code samples are supplied so there is no indication how to actually create this in your own Xaml app.

In this blogpost I will show the different steps to get the basics done and I will supply the source code for you to use.

The examples

For mobile

Example design from pivot guidelines by Microsoft

For desktop

Example design for desktop from pivot guidelines by Microsoft

The default Pivot

The default Pivot looks just like the pivot we know from Windows Phone.

<PivotItem Header="item 1">
    <TextBlock>Content 1</TextBlock>
</PivotItem>

Default Pivot in a UWP app

Adding an icon to the header

So the first step is to add an icon and do some styling. A bit lazy I used the Pivot sample from the Windows Universal Samples as a starting point.

<PivotItem>
    <PivotItem.Header>
        <local:TabHeader Label="item 1" Glyph="&amp;#xE716;" />
    </PivotItem.Header>
    <TextBlock>Content 1</TextBlock>
</PivotItem>

Icon in Pivot Header with problem

Immediatly we spot a problem. It seems the Pivot Header has a fixed height.
Browsing around I found a MSDN forum post and a Stack Overflow question about this. Both are resolved using code to adjust the height of the items.

Because we want a responsive solution where the height is not known beforehand, code is not the best option.
Lucky for us, Microsoft has added the Live Visual Tree tool in Visual Studio 2015 making it possible to debug what is happening in the app at runtime. This shows that the PivotHeaderItem has a default Style with a fixed height.

Visual Studio 2015 Live Visual Tree showing the fixed height from the default template

The problem is that Visual Studio does not have any option to edit (a copy of) this template. So we have to get it the hard way.

To find the default template of every control and style in UWP apps we have to go to the following file:

%ProgramFiles(x86)%\Windows Kits\10\DesignTime\CommonConfiguration\Neutral
                                    \UAP\10.0.10240.0\Generic\generic.xaml

Look for the PivotHeaderItem template and copy it to the Resources Dictionary for your preferred scope.
In the Style we change the Height to Auto.

<Setter Property="Height" Value="Auto" />

If the height of your pivot header can be less than 36 you will also need the modify the height of the Previous and Next buttons in the Pivot Header as these have a fixed height too. These changes are made in the Pivot Style.

<Button x:Name="PreviousButton" ... Height="Auto" ... />
<Button x:Name="NextButton" ... Height="Auto"  ... />

Create a copy of the Pivot Style

If you don’t know how to edit a copy of a Style, here are the 3 steps to follow:

  1. Select the Pivot in the Document Outline
  2. Right Click and select "Edit Template"
  3. Choose "Edit a Copy..."

Make the Pivot Header Item reponsive

First I will list how I want the header items to repond:

  • If the app is narrow, the icon is centered above the label
  • If the app is wide, the label is on the right side of the icon
  • The transition from narrow to wide is at 500

Getting this working is quite easy in UWP apps without writing any code at all.
For this we use the new AdaptiveTrigger and the RelativePanel.

We alter the TabHeader.xaml adding a RelativePanel for layout and VisualStates for the transition. Something like this:

<VisualStateManager.VisualStateGroups>
    <VisualStateGroup>
        <VisualState x:Name="Narrow">
            <VisualState.StateTriggers>
                <AdaptiveTrigger MinWindowWidth="0" />
            </VisualState.StateTriggers>
            <VisualState.Setters>
                <Setter Target="Icon.(RelativePanel.AlignHorizontalCenterWithPanel)" Value="True" />
                <Setter Target="LabelText.(RelativePanel.Below)" Value="Icon" />
                <Setter Target="LabelText.(RelativePanel.AlignHorizontalCenterWith)" Value="Icon" />
            </VisualState.Setters>
        </VisualState>
        <VisualState x:Name="Wide">
            <VisualState.StateTriggers>
                <AdaptiveTrigger MinWindowWidth="500" />
            </VisualState.StateTriggers>
            <VisualState.Setters>
                <Setter Target="Icon.(RelativePanel.AlignVerticalCenterWithPanel)" Value="True" />
                <Setter Target="LabelText.(RelativePanel.RightOf)" Value="Icon" />
                <Setter Target="LabelText.(RelativePanel.AlignVerticalCenterWith)" Value="Icon" />
                <Setter Target="RelativePanel.Margin" Value="0,0,12,0"/>
                <Setter Target="Icon.Margin" Value="0,0,0,0"/>
            </VisualState.Setters>
        </VisualState>
    </VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<RelativePanel x:Name="RelativePanel">
    <FontIcon x:Name="Icon"
                HorizontalAlignment="Center"
                Margin="0,12,0,0"
                Glyph="{Binding Glyph}"
                FontSize="16" />
    <TextBlock x:Name="LabelText"
                Text="{Binding Label}"
                Style="{StaticResource CaptionTextBlockStyle}"
                Margin="2,4,2,4" />
</RelativePanel>

Run the app and resize it so we see the pivot items change when it's wide enough.
Responsive Pivot Header Items

Aligning the Pivot Header Items

I like it when the pivot items are centered in the mobile layout. To achieve this we need to add the Visual States to the Pivot Style.
If you didn’t have a Pivot Style already look in the previous section how to create a copy of the Style.

We add the Visual State Group the existing VisualStateManager.VisualStateGroups in the RootElement of the Pivot ControlTemplate:

<VisualStateGroup>
    <VisualState x:Name="Narrow">
        <VisualState.StateTriggers>
            <AdaptiveTrigger MinWindowWidth="0" />
        </VisualState.StateTriggers>
        <VisualState.Setters>
            <Setter Target="HeaderClipper.HorizontalContentAlignment" Value="Center" />
        </VisualState.Setters>
    </VisualState>
    <VisualState x:Name="Wide">
        <VisualState.StateTriggers>
            <AdaptiveTrigger MinWindowWidth="500" />
        </VisualState.StateTriggers>
        <VisualState.Setters>
            <Setter Target="HeaderClipper.HorizontalContentAlignment" Value="Stretch" />
        </VisualState.Setters>
    </VisualState>
</VisualStateGroup>

Now the items are centered when the app is “narrow”, and left aligned when the app is “wide”.
The Pivot Header Items centered

Source code

You can download my Universal Windows Platform App sample project on GitHub.

31 Comments

  1. /

    Hi,
    how can I change the Background Color of the headers like you're showing in the first two pictures? I mean the headeritem selected background and unselected background?!

    Thank you!!

    • /

      Hi Paul,

      Great question. It's quite easy with 3 small changes to the XAML.

      1. In the PivotHeaderItem Style you can add a Setter to change the RequestedTheme to Dark.
      2. In the same Style you change Background color for the Selected Visual State to the lighter background color.
      3. In the Pivot Template go to the PivotPanel and add a Border with the Background color set to the darker color. Like this:
        <Border Background="#FF34323F" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>

        That's all.

        You inspired me to write a separate blogpost about this. Thanks!

  2. /

    Hey,

    Thank you very much for your quick response!!! It's quite that what I was swarching for!!!

    Thank you!

  3. /

    Many many thanks for your blogpost. I want to show an underline on selected pivot item and also want to change the white color of icons and text. What i need to do?

    • /

      You can change the color of the text and icon by changing the ForeGround. And changing the underline can be done just like I set the BackGround color in the post Highlight your Selected Pivot Header in a Universal Windows Platform app

    • /

      Thank you for your example. Something like this in the PivotHeaderItem Style will work:

      1. Add to the Visual State "Selected" the following
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Border" Storyboard.TargetProperty="BorderBrush">
            <DiscreteObjectKeyFrame KeyTime="0" Value="Red" />
        </ObjectAnimationUsingKeyFrames>
      2. Add, just before the ContentPresenter the following:
        <Border x:Name="Border" BorderBrush="Transparent" BorderThickness="0,0,0,2"/>
      • /

        You saved my day brother. Many many thanks. It works like a charm :D

  4. /

    When I try to open the example project (downloaded from GIthub) I get that the XAML is "invalid-markup". See screenshot:
    http://s7.postimg.org/mq4tpxvob/failed.jpg

    • /

      I think you need to build the project first so the designer knows about the custom contols.

      • /

        I have this problem too, when I compile the solution shows this error:
        UnauthorizedAccessException: Accesso negato. (Eccezione da HRESULT: 0x80070005 (E_ACCESSDENIED))
        StackTrace:
        at Windows.UI.Xaml.Setter.put_Value(Object value)
        at Microsoft.VisualStudio.DesignTools.UniversalXamlDesigner.UniversalXamlUIElementDesignTimeProperties.SetterValueCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        at Windows.UI.Xaml.UIElement.UpdateLayout()
        at Microsoft.VisualStudio.DesignTools.WindowsXamlDesigner.Views.WindowsUIXamlImageHost.WindowsXamlSceneWrapper.UpdateLayout()
        at Microsoft.VisualStudio.DesignTools.WindowsXamlDesigner.Views.WindowsUIXamlImageHost.set_RootInstance(Object value)
        InnerException: nessuna

      • /

        Hi Michael!

        After rebuilding the problem dissapeared, but now I get the same problem as massijay. Spent over a week trying to get this to work, thinking of dropping UWP altogether and go with WPF instead.

      • /

        I spent a couple of minutes debugging this. Accessing the ThemeResource from the lines below causes the AccessDenied exception. I don't know what's the reason, though. Replacing the values from generic.xaml work.

        Hope massijay and Jakob get the message across ;)

  5. /

    how to make the pivot headers to occupy the whole screen width?

  6. /

    Is it possible to hide pivot headers when we scroll down to a listview or gridview?

  7. /

    Hi Michael, thanks for your post!

    I'm trying to make the selected header item Bold, but without success... this is what i done in

    Something what i've missed?

    Thank you very much

    • /

      I'm sorry but the code snippet that i insert not worked...

      VisualState x:Name="Selected" is the section where i put this animation

      ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="FontWeight"
      DiscreteObjectKeyFrame KeyTime="0" Value="Bold"
      ObjectAnimationUsingKeyFrames

  8. /

    For mobile use, I want the pivot tab on the bottom of the screen , How to do that?
    And one more question, is it possible to change the PivotHeader icons to images instead of FontIcon ? If it's possible, how to do it ?

  9. /

    How to change the PivotHeader icons to images ?

  10. /

    Hi Michaël, Thanks for this project. However this project seems to not work on the 10586 build. I get this in the designer:

    UnauthorizedAccessException: Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))

    StackTrace:
    at Windows.UI.Xaml.Setter.put_Value(Object value)
    at Microsoft.VisualStudio.DesignTools.UniversalXamlDesigner.UniversalXamlUIElementDesignTimeProperties.SetterValueCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
    at Windows.UI.Xaml.UIElement.UpdateLayout()
    at Microsoft.VisualStudio.DesignTools.WindowsXamlDesigner.Views.WindowsUIXamlImageHost.WindowsXamlSceneWrapper.UpdateLayout()
    at Microsoft.VisualStudio.DesignTools.WindowsXamlDesigner.Views.WindowsUIXamlImageHost.set_RootInstance(Object value)

    When I run it though it seems ok but obviously not having the designer is a problem.

    Any Ideas

    • /

      It seems to be caused by setting the requested theme in PivotHeaderItem

      May have to set the font colours manually.

  11. /

    Can anyone tell me how to put a close button on PivotItems like they did for Edge?

  12. /

    Nice work! You very help me, thank you very much!

  13. /

    Glyph=""

    Here the value "&#xE716" gives an icon of people
    I need different icons. Like one of the AppBarButton icon values
    How to get them
    what value has to be given to get one of those.

  14. /

    I'm having trouble getting the content to scroll inside the pivot content. It doesn't scroll no matter what I do and I don't know how to fix this?

    • /

      Do you add a ScrollViewer to your Pivot Panel?

  15. /

    How do you make the tabs stretch across the whole window width when in mobile view like the example provided by Microsoft shows?

Trackbacks and Pingbacks

  1. Highlight your Selected Pivot Header in a Universal Windows Platform app | Michaël’s coding thoughts

Leave a comment