New to Telerik UI for WPF? Download free 30-day trial

How to apply different templates for front and back cover page

Currently RadBook does not expose separate properties for setting templates for the front and back cover pages(first and last pages in RadBook's items collection). In this case, you can use the already available DataTemplateSelectors - LeftPageTemplateSelector and RightPageTemplateSelector. Depending on the index of each page, we will decide what template to apply on the page.

First, lets begin by creating 4 different templates:

  • front cover page template

  • left inner page template

  • right inner page template

  • back cover page template

For the sake of the example, each template will will have the following structure:

WPF RadBook Page Structure

This how the four templates look like in XAML code:

Example 1: Setting up the page templates

<!--  Front Cover Template  --> 
<DataTemplate x:Key="FrontCoverTemplate"> 
    <Border BorderBrush="Black" BorderThickness="1"> 
        <Grid Background="LightGray"> 
            <Grid.RowDefinitions> 
                <RowDefinition /> 
                <RowDefinition Height="Auto" /> 
            </Grid.RowDefinitions> 
            <TextBlock HorizontalAlignment="Center"  
                        VerticalAlignment="Center" 
                        FontSize="50" 
                        FontWeight="Bold" 
                        Text="FRONT" /> 
            <StackPanel Grid.Row="1"  
                        HorizontalAlignment="Center" 
                        Orientation="Horizontal"> 
                <TextBlock FontSize="20" Text="Page #" /> 
                <TextBlock FontSize="20"  
                            FontWeight="Bold" 
                            Text="{Binding}" /> 
            </StackPanel> 
        </Grid> 
    </Border> 
</DataTemplate> 
 
<!--  Inner Left Page Template  --> 
<DataTemplate x:Key="LeftPageTemplate"> 
    <Border BorderBrush="Black" BorderThickness="1"> 
        <Grid Background="LightGreen"> 
            <Grid.RowDefinitions> 
                <RowDefinition /> 
                <RowDefinition Height="Auto" /> 
            </Grid.RowDefinitions> 
            <TextBlock HorizontalAlignment="Center"  
                        VerticalAlignment="Center" 
                        FontSize="50" 
                        FontWeight="Bold" 
                        Text="LEFT" /> 
            <StackPanel Grid.Row="1"  
                        HorizontalAlignment="Center" 
                        Orientation="Horizontal"> 
                <TextBlock FontSize="20" Text="Page #" /> 
                <TextBlock FontSize="20"  
                            FontWeight="Bold" 
                            Text="{Binding}" /> 
            </StackPanel> 
        </Grid> 
    </Border> 
</DataTemplate> 
 
<!--  Inner Right Page Template  --> 
<DataTemplate x:Key="RightPageTemplate"> 
    <Border BorderBrush="Black" BorderThickness="1"> 
        <Grid Background="LightPink"> 
            <Grid.RowDefinitions> 
                <RowDefinition /> 
                <RowDefinition Height="Auto" /> 
            </Grid.RowDefinitions> 
            <TextBlock HorizontalAlignment="Center"  
                        VerticalAlignment="Center" 
                        FontSize="50" 
                        FontWeight="Bold" 
                        Text="RIGHT" /> 
            <StackPanel Grid.Row="1"  
                        HorizontalAlignment="Center" 
                        Orientation="Horizontal"> 
                <TextBlock FontSize="20" Text="Page #" /> 
                <TextBlock FontSize="20"  
                            FontWeight="Bold" 
                            Text="{Binding}" /> 
            </StackPanel> 
        </Grid> 
    </Border> 
</DataTemplate> 
 
<!--  Back Cover Template  --> 
<DataTemplate x:Key="BackCoverTemplate"> 
    <Border BorderBrush="Black" BorderThickness="1"> 
        <Grid Background="LightYellow"> 
            <Grid.RowDefinitions> 
                <RowDefinition /> 
                <RowDefinition Height="Auto" /> 
            </Grid.RowDefinitions> 
            <TextBlock HorizontalAlignment="Center"  
                        VerticalAlignment="Center" 
                        FontSize="50" 
                        FontWeight="Bold" 
                        Text="BACK" /> 
            <StackPanel Grid.Row="1"  
                        HorizontalAlignment="Center" 
                        Orientation="Horizontal"> 
                <TextBlock FontSize="20" Text="Page #" /> 
                <TextBlock FontSize="20"  
                            FontWeight="Bold" 
                            Text="{Binding}" /> 
            </StackPanel> 
        </Grid> 
    </Border> 
</DataTemplate> 

The next step is to create two DataTemplateSelectors, that will take care of picking the right template out. The first DataTemplateSelector will provide template for the front cover page and every consecutive right page, while the second DataTemplateSelector will provide template for the back cover page and every consecutive left page.

Example 2: Defining the template selectors

/// <summary> 
 /// DataTemplateSelector responsible for picking template for the back cover page and every consecutive left page. 
 /// </summary> 
 public class LeftPageTemplateSelector : DataTemplateSelector 
 { 
  /// <summary> 
  /// Gets or sets the back cover template. 
  /// </summary> 
  /// <value>The back cover template.</value> 
  public DataTemplate BackCoverTemplate { get; set; } 
  /// <summary> 
  /// Gets or sets template for every left page in the book, except only in the case of a last page. 
  /// </summary> 
  /// <value>The left page template.</value> 
  public DataTemplate LeftPageTemplate { get; set; } 
  public override DataTemplate SelectTemplate(object item, DependencyObject container) 
  { 
   RadBookItem page = container as RadBookItem; 
   // we need an instance of the book so that we can determine the whether the current page is the last page. 
   RadBook book = System.Windows.Controls.ItemsControl.ItemsControlFromItemContainer(container) as RadBook; 
   // Using the index property, we can determine whether the page is last page or it is one of the inner left pages. 
   if (page.Index == book.Items.Count - 1) 
   { 
    return this.BackCoverTemplate; 
   } 
   else 
   { 
    return this.LeftPageTemplate; 
   } 
  } 
 } 
 /// <summary> 
 /// DataTemplateSelector responsible for picking template for the fron cover page and every consecutive right page. 
 /// </summary> 
 public class RightPageTemplateSelector : DataTemplateSelector 
 { 
  /// <summary> 
  /// Gets or sets the front cover template. 
  /// </summary> 
  /// <value>The front cover template.</value> 
  public DataTemplate FrontCoverTemplate { get; set; } 
  /// <summary> 
  /// Gets or sets template for every right page in the book, except only in the case of a first page. 
  /// </summary> 
  /// <value>The right page template.</value> 
  public DataTemplate RightPageTemplate { get; set; } 
  public override DataTemplate SelectTemplate(object item, DependencyObject container) 
  { 
   RadBookItem page = container as RadBookItem; 
   // Using the index property, we can determine whether the page is first page or it is one of the inner right pages. 
   if (page.Index == 0) 
   { 
    return this.FrontCoverTemplate; 
   } 
   else 
   { 
    return this.RightPageTemplate; 
   } 
  } 
 } 
''' <summary> ''' 
''' DataTemplateSelector responsible for picking template for the back cover page and every consecutive left page. ''' 
''' </summary> ''' 
Public Class LeftPageTemplateSelector 
    Inherits DataTemplateSelector 
    ''' <summary> ''' 
    ''' Gets or sets the back cover template. ''' 
    ''' </summary> ''' 
    ''' <value>The back cover template.</value> ''' 
    Public Property BackCoverTemplate() As DataTemplate 
        Get 
            Return m_BackCoverTemplate 
        End Get 
        Set(ByVal value As DataTemplate) 
            m_BackCoverTemplate = Value 
        End Set 
    End Property 
    Private m_BackCoverTemplate As DataTemplate 
    ''' <summary> ''' 
    ''' Gets or sets template for every left page in the book, except only in the case of a last page. ''' 
    ''' </summary> ''' 
    ''' <value>The left page template.</value> ''' 
    Public Property LeftPageTemplate() As DataTemplate 
        Get 
            Return m_LeftPageTemplate 
        End Get 
        Set(ByVal value As DataTemplate) 
            m_LeftPageTemplate = Value 
        End Set 
    End Property 
    Private m_LeftPageTemplate As DataTemplate 
    Public Overrides Function SelectTemplate(ByVal item As Object, ByVal container As DependencyObject) As DataTemplate 
        Dim page As RadBookItem = TryCast(container, RadBookItem) 
        ' we need an instance of the book so that we can determine the whether the current page is the last page. ' 
        Dim book As RadBook = TryCast(System.Windows.Controls.ItemsControl.ItemsControlFromItemContainer(container), RadBook) 
        ' Using the index property, we can determine whether the page is last page or it is one of the inner left pages. ' 
        If page.Index = book.Items.Count - 1 Then 
            Return Me.BackCoverTemplate 
        Else 
            Return Me.LeftPageTemplate 
        End If 
    End Function 
End Class 
''' <summary> ''' 
''' DataTemplateSelector responsible for picking template for the fron cover page and every consecutive right page. ''' 
''' </summary> ''' 
Public Class RightPageTemplateSelector 
    Inherits DataTemplateSelector 
    ''' <summary> ''' 
    ''' Gets or sets the front cover template. ''' 
    ''' </summary> ''' 
    ''' <value>The front cover template.</value> ''' 
    Public Property FrontCoverTemplate() As DataTemplate 
        Get 
            Return m_FrontCoverTemplate 
        End Get 
        Set(ByVal value As DataTemplate) 
            m_FrontCoverTemplate = Value 
        End Set 
    End Property 
    Private m_FrontCoverTemplate As DataTemplate 
    ''' <summary> ''' 
    ''' Gets or sets template for every right page in the book, except only in the case of a first page. ''' 
    ''' </summary> ''' 
    ''' <value>The right page template.</value> ''' 
    Public Property RightPageTemplate() As DataTemplate 
        Get 
            Return m_RightPageTemplate 
        End Get 
        Set(ByVal value As DataTemplate) 
            m_RightPageTemplate = Value 
        End Set 
    End Property 
    Private m_RightPageTemplate As DataTemplate 
    Public Overrides Function SelectTemplate(ByVal item As Object, ByVal container As DependencyObject) As DataTemplate 
        Dim page As RadBookItem = TryCast(container, RadBookItem) 
        ' Using the index property, we can determine whether the page is first page or it is one of the inner right pages. ' 
        If page.Index = 0 Then 
            Return Me.FrontCoverTemplate 
        Else 
            Return Me.RightPageTemplate 
        End If 
    End Function 
End Class 

Next, we can instantiate the two template selectors in XAML...

Example 3: Adding the template selectors in XAML

<local:LeftPageTemplateSelector x:Key="LeftPageTemplateSelector" 
        BackCoverTemplate="{StaticResource BackCoverTemplate}" LeftPageTemplate="{StaticResource LeftPageTemplate}" /> 
<local:RightPageTemplateSelector x:Key="RightPageTemplateSelector" 
        FrontCoverTemplate="{StaticResource FrontCoverTemplate}" 
        RightPageTemplate="{StaticResource RightPageTemplate}" /> 

... and pass them to the book:

Example 4: Passing the template selectors to the RadBook control

<telerik:RadBook x:Name="book1"  
                 FirstPagePosition="Right" 
                 LeftPageTemplateSelector="{StaticResource LeftPageTemplateSelector}" 
                 RightPageIndex="0" 
                 RightPageTemplateSelector="{StaticResource RightPageTemplateSelector}" /> 

Finally, all we have to do is populate the book with items. In this example, the book will be bound to an array of numbers.

Example 5: Setting the ItemsSource of the RadBook control

public partial class MainPage : UserControl 
 { 
  public MainPage() 
  { 
   InitializeComponent(); 
   this.book1.ItemsSource = Enumerable.Range(0, 10); 
  } 
 } 
Partial Public Class MainPage 
    Inherits UserControl 
    Public Sub New() 
        InitializeComponent() 
        book1.ItemsSource = Enumerable.Range(0, 10) 
    End Sub 
End Class 

This is how the final result looks like:

WPF RadBook Custom Template Front   WPF RadBook Custom Template Left and Right

WPF RadBook Custom Template Back

In this article