extending the windows phone pivot

As I was working on a Windows Phone 8 project I needed a pivot that could hide its title, giving back some screen real-estate when needed. The basic pivot that is included in the Windows Phone SDK doesn’t have this kind of behavior so it was a great opportunity to try out custom controls in Windows Phone. I’ve build custom controls in XAML before but never based on an existing one, so fun times ahead. Let me start by showing a side-by-side comparison between both views of my pivot.

don’t mind the overlapping textblock and button, point is that when the button is clicked, the title of the pivot disappears.

Building a XAML custom control

It’s quite easy to build a custom control in XAML as long as you follow the guidelines. It requires you to add a folder called Themes and in the folder a file called generic.xaml. The generic.xaml file is a resource dictionary, no code behind file is needed. Do follow the naming conventions exactly or your control won’t work. Next step is adding a class that inherits from ContentControl (or a control that already inherits from ContentControl). The project for my ExtendedPivot looks like this

The project type is a WP8 class library containing two custom controls, one for the pivot and one for the pivot items.

Extending the pivot

Since I only want to add a functionality to an existing control, the Pivot, my ExtendedPivot class inherits from Pivot instead of CustomControl.

Code Snippet
  1. publicclassExtendedPivot : Pivot
  2. {
  3.     publicstaticreadonlyDependencyProperty HeaderVisibilityProperty =
  4.         DependencyProperty.Register("HeaderVisibilityProperty", typeof (Visibility), typeof (ExtendedPivot), newPropertyMetadata(null));
  6.     publicVisibility HeaderVisibility
  7.     {
  8.         get { return (Visibility)GetValue(HeaderVisibilityProperty); }
  9.         set { SetValue(HeaderVisibilityProperty, value); }
  10.     }
  12.     public ExtendedPivot()
  13.     {
  14.         DefaultStyleKey =  typeof(ExtendedPivot);
  15.     }
  16. }

We’ll start with the constructor, Line 14 is necessary when developing a custom control, it sets the style of the control to the style defined in generic.xaml (we’ll get to that style in a minute). Lines 6 – 10 are a property that will be used by the DependencyProperty. The DependencyProperty (lines 3-4) is a property that we can bind a value to when using the control in a project, it might seem a bit overwhelming at first but there’s a great snippet in VS2012 to easily write them. Basically, the parameters for the Register function are a name, the type of the property, the owner type (type of the control where you’re declaring the DP) and some metadata.

The get and set method of the normal property use the DP to get and set values through databinding.


This is the style for the ExtendedPivot as declared in generic.xaml

Code Snippet
  1. <Style TargetType="local:ExtendedPivot">
  2.     <Setter Property="Margin" Value="0" />
  3.     <Setter Property="Padding" Value="0" />
  4.     <Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}" />
  5.     <Setter Property="Background" Value="Transparent" />
  6.     <Setter Property="ItemsPanel">
  7.         <Setter.Value>
  8.             <ItemsPanelTemplate>
  9.                 <Grid />
  10.             </ItemsPanelTemplate>
  11.         </Setter.Value>
  12.     </Setter>
  13.     <Setter Property="Template">
  14.         <Setter.Value>
  15.             <ControlTemplate TargetType="local:ExtendedPivot">
  16.                 <Grid HorizontalAlignment="{TemplateBinding HorizontalAlignment}" VerticalAlignment="{TemplateBinding VerticalAlignment}">
  17.                     <Grid.RowDefinitions>
  18.                         <RowDefinition Height="Auto" />
  19.                         <RowDefinition Height="Auto" />
  20.                         <RowDefinition Height="*" />
  21.                     </Grid.RowDefinitions>
  22.                     <Grid Grid.RowSpan="3" Background="{TemplateBinding Background}" />
  23.                     <ContentControl Grid.Row="0"
  24.                                     Margin="24,17,0,-7"
  25.                                     HorizontalAlignment="Left"
  26.                                     Content="{TemplateBinding Title}"
  27.                                     ContentTemplate="{TemplateBinding TitleTemplate}"
  28.                                     Visibility="{TemplateBinding HeaderVisibility}" />
  29.                     <primitives:PivotHeadersControl x:Name="HeadersListElement" Grid.Row="1" />
  30.                     <ItemsPresenter x:Name="PivotItemPresenter"
  31.                                     Grid.Row="2"
  32.                                     Margin="{TemplateBinding Padding}" />
  33.                 </Grid>
  34.             </ControlTemplate>
  35.         </Setter.Value>
  36.     </Setter>
  37. </Style>

Basically, I’ve created a xaml page in some very basic Windows Phone project, right-clicked it, selected Edit Template > Edit a copy. This gives you a copy of the template for the Pivot. I copied that template in the generic.xaml style. The ContentControl at Lines 23-28 show the title in the pivot. I added the Visiblity property here and bound it to the HeaderVisibility property in the ExtendedPivot class. To bind a property in a style you need to use the TemplateBinding keyword instead of the normal Binding one.

Don’t forget to set TargetType to the type of your custom control.

Using the custom control in an app

The control is ready, now it’s time to use it. Create a new Windows Phone app and reference the project or DLL of the custom control. This is the MainPage of the sample app.

Code Snippet
  1. <phone:PhoneApplicationPage x:Class="ExtendedPivot.MainPage"
  2.                             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3.                             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4.                             xmlns:control="clr-namespace:ExtendedPivot.Control;assembly=ExtendedPivot.Control"
  5.                             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  6.                             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  7.                             xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
  8.                             xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
  9.                             FontFamily="{StaticResource PhoneFontFamilyNormal}"
  10.                             FontSize="{StaticResource PhoneFontSizeNormal}"
  11.                             Foreground="{StaticResource PhoneForegroundBrush}"
  12.                             Orientation="Portrait"
  13.                             SupportedOrientations="Portrait"
  14.                             shell:SystemTray.IsVisible="True"
  15.                             mc:Ignorable="d">
  17.     <!--  LayoutRoot is the root grid where all page content is placed  -->
  18.     <Grid x:Name="LayoutRoot" Background="Transparent">
  19.         <!--  Pivot Control  -->
  20.         <control:ExtendedPivot HeaderVisibility="{Binding Visibility}" Title="MY APPLICATION">
  21.             <control:ExtendedPivotItem Header="item 1">
  22.                 <Grid>
  23.                     <TextBlock Text="item1" />
  24.                     <Button Click="ButtonBase_OnClick" Content="button" />
  25.                 </Grid>
  26.             </control:ExtendedPivotItem>
  28.             <control:ExtendedPivotItem Header="item 2">
  29.                 <TextBlock Text="item2" />
  30.             </control:ExtendedPivotItem>
  31.         </control:ExtendedPivot>
  32.     </Grid>
  33. </phone:PhoneApplicationPage>

Line 4 defines the namespace that holds the ExtendedPivot. Line 20 puts the control on the actual page. Notice that we bind the HeaderVisibility property of our control. I defined the datacontext of this page in code behind to be of type MainViewModel. MainViewModel implements INotifyPropertyChanged and only holds one property of type Visibility, that property is bound to the ExtendedPivot’s HeaderVisibility.

The Button in the pivot will switch the HeaderVisibility between Collapsed and Visible, this happens in the code behind of this page.

Code Snippet
  1. publicpartialclassMainPage : PhoneApplicationPage
  2. {
  3.     privateMainViewModel _mainViewModel;
  5.     // Constructor
  6.     public MainPage()
  7.     {
  8.         InitializeComponent();
  10.         _mainViewModel = newMainViewModel();
  12.         DataContext = _mainViewModel;
  13.     }
  15.     privatevoid ButtonBase_OnClick(object sender, RoutedEventArgs e)
  16.     {
  17.         if (_mainViewModel.Visibility == Visibility.Collapsed)
  18.         {
  19.             _mainViewModel.Visibility = Visibility.Visible;            
  20.         }
  21.         else
  22.         {
  23.             _mainViewModel.Visibility = Visibility.Collapsed;          
  24.         }
  25.     }
  26. }

Not really the best way of writing a Windows Phone app but it’s just for making the point Glimlach


Extending a Windows Phone control isn’t hard as long as you follow the naming conventions, adding some extra functionality is as easy as copying the xaml template and adding some dependency properties.

The sample code can be found on my SkyDrive


Leave a Comment