# Template Customization

## Content

A template is used in software applications to specify how data, documents, or UI elements are presented visually, either on screen or when printed. They provide an organized way to define and instantiate common patterns or layouts that can be used throughout an application, such as page numbers, document title, author name, dates, etc.

You can also create a template( or data template) for the **C1RichTextBox** control to provide a consistent layout while displaying its content. Moreover, the template also helps you control how the content appears on the printed page, including margins, headers, footers, and other printing-specific elements. For example, you can display the header and footer on each page of a multi-page document while displaying it within the **C1RichTextBox** control.

![Header/Footer](https://cdn.mescius.io/document-site-files/images/f14c4281-7088-4b33-9b40-4a5f7acf258d/images/rtb_header_footer_new.gif)

Following section explains how you can create and customize a template using .NET and .NET Framework versions to display headers and footers on a multi-page RTF document within the **C1RichTextBox** control.

1. In the XAML view, create a simple data template with the name printtemplate containing some predefined styles for displaying data. The template uses the **C1LayoutTransformer** class to apply styles to different elements of data, as shown in the given code snippet.
2. Add two TextBlock elements in the **C1LayoutTransformer** class to display header and footer on a document. Adding these **\<TextBlock>** elements for displaying the header and footer allows you to customize the existing data template.
3. Set the header and footer of the document by using the **Text** property of the first and second **TextBlock** elements. For example, the **Text** property of the first TextBlock element is set to show a simple text message, whereas the Text property of the second **TextBlock** element is set to show page numbers.
4. Bind the **Text** property of the second **TextBlock** element with the **Index** property of the data context. Since, the **Index** property starts index from 0, therefore, you need to create a converter class such as **PageNumberConverter** to start the index from 1 for properly displaying page numbers in the footer of document.

    ```xml
    <Window.Resources>
        <local:PageNumberConverter x:Key="PageNumberConverter"></local:PageNumberConverter>        
        <DataTemplate x:Key="printtemplate">
            <Grid Margin="4">
                <Grid.Resources>
                    <c1:ZoomToScaleTransformConverter x:Key="zoomConverter" />
                </Grid.Resources>
                <Border BorderThickness="1" BorderBrush="#FF646464" Grid.Row="1" Grid.Column="1" Background="{Binding ViewManager.PresenterInfo.Background}">
                    <Border.Effect>
                        <DropShadowEffect Opacity="0.3" />
                    </Border.Effect>
                </Border>
                <c1:C1LayoutTransformer LayoutTransform="{Binding ViewManager.PresenterInfo.Zoom, Converter={StaticResource zoomConverter}}">
                    <Grid Height="{Binding ViewManager.PresenterInfo.Height}" Width="{Binding ViewManager.PresenterInfo.Width}">
                        <c1:C1RichTextPresenter Source="{Binding}" Grid.Row="1" Grid.Column="1" Margin="{Binding ViewManager.PresenterInfo.Padding}"/>
                        <TextBlock Text="{Binding Index,StringFormat='Mark Twain'}" HorizontalAlignment="Right"  VerticalAlignment="Top" 
                                  FontWeight="UltraBold"  FontSize="16" Margin="50" Foreground="Red" />
                       <TextBlock Text="{Binding Index,Converter={StaticResource PageNumberConverter}}" HorizontalAlignment="Right"  
                                  VerticalAlignment="Bottom" FontStyle="Italic" FontSize="14" Margin="50" Foreground="Green" />
                    </Grid>
                </c1:C1LayoutTransformer>
            </Grid>
        </DataTemplate>
    </Window.Resources>
    ```
5. Bind the template with the RTF document with the **C1RichTextbox** control using its **PrintTemplate** property, as shown in the following code snippet:

    ```xml
    <Grid>
        <c1:C1RichTextBox PrintTemplate="{StaticResource printtemplate}"  x:Name="rtb" Grid.Row="1" Grid.Column="1" Margin="{Binding ViewManager.PresenterInfo.Padding}"/>
    </Grid>
    ```
6. Load the RTF document into the **C1RichTextbox** control using the **Application** class that provides the **GetResourceStream** method to retrieve a resource stream on the basis of the provided URI. The URI contains the location of the RTF document.
7. Initialize a new **StreamReader** object with the obtained stream to read the entire RTF content of the stream to the end using the **ReadToEnd** method.
8. Convert the RTF content into **C1RichTextBox** document using the **ConvertToDocument** method of the **RtfFilter** class. The **C1RichTextbox** control uses the **Document** method for this conversion.
9. Display content in a print layout mode using the **ViewMode** property of the **C1RichTextbox** control to get an idea how the content appears when printed, as shown in the following code snippet:

    ```csharp
    var stream = Application.GetResourceStream(new Uri("./../Resources/MarkTwain.rtf", UriKind.RelativeOrAbsolute)).Stream;
    var rtf = new StreamReader(stream).ReadToEnd();
    rtb.Document = new RtfFilter().ConvertToDocument(rtf);
    rtb.ViewMode = TextViewMode.Print;         
    ```

    ```vbnet
    Dim stream = Application.GetResourceStream(New Uri("./../Resources/MarkTwain.rtf", UriKind.Relative)).Stream           
    Dim rtf = New StreamReader(stream).ReadToEnd()
    rtb.Document = New RtfFilter().ConvertToDocument(rtf)
    rtb.ViewMode = TextViewMode.Print
    ```
10. Add the following **PageNumberConverter** class to display page numbers from 1. The **PageNumberConverter** class uses the **IValueConverter** interface to convert integer page numbers into formatted strings for displaying footer messages. The **IValueConverter** interface contains **Convert** and **ConvertBack** methods for converting values from one type to another for data binding:

    ```csharp
    public class PageNumberConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is int index)
            {
                return $"{index + 1}";
            }
            return string.Empty;
        }
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    ```

    ```vbnet
    Public Class PageNumberConverter
        Implements IValueConverter
        Public Function Convert(value As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IValueConverter.Convert
            If TypeOf value Is Integer Then
                Dim index As Integer = DirectCast(value, Integer)
                Return $"{index + 1}"
            End If
            Return String.Empty
        End Function
        Public Function ConvertBack(value As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IValueConverter.ConvertBack
            Throw New NotImplementedException()
        End Function
    End Class
    ```

On running the application, you can see header and footer on each page of the RTF document within the **C1RichTextbox** control.