Intersoft ClientUI Documentation
How-to: Use Custom Paginator to Print FlowDocument

This example shows how use a custom paginator which is applied when printing a FlowDocument. In this example, FlowDocument is hosted in a UXFlowDocumentViewer control. However, you can specify a custom paginator in FlowDocument regardless of the viewer.

Example

Description

PrintDocument class will use the Print method to print the document. Print method needs two parameters, DocumentPaginator object and the document name. DocumentPaginator is an abstract base class that supports creation of multiple-page elements from a single document. By default, each FlowDocument has DocumentPaginator property that contain DocumentPaginator object for the flow document.

When FlowDocument is in page mode, the document content will flow according to the specified page configuration. If FlowDocument is in scroll mode, the document content will flow according to the available view port. In Silverlight application, you can choose a page size in the Print dialog window. In this case, the DocumentPaginator will create multiple page elements, despite of whether the FlowDocument is in page mode or scroll mode, for printing purpose with the selected page size. Unlike Silverlight applications, the selected page size in the Print dialog window is not used in WPF application. If you need to specify different page size for printing purpose, you can specify the page size in the custom paginator definition. You can also specify a custom paginator class to add custom elements for printing purpose only, such as header or footer.

The following code shows how to add header and footer element in a FlowDocument for printing purpose.

Code

Custom Paginator Class
Copy Code
public class FlowDocCustomPaginator : DocumentPaginator
{
    private Size _pageSize;
    private DocumentPaginator _paginator;

    public FlowDocCustomPaginator(DocumentPaginator paginator, Size pageSize)
    {
        this._pageSize = pageSize;
        this._paginator = paginator;
    }

    public override DocumentPage GetPage(int pageNumber)
    {
        DocumentPage page = _paginator.GetPage(pageNumber);
        Grid grid = new Grid();

        //add header element
        TextBlock tb = new TextBlock();
        tb.Text = "Health Article";
        tb.FontSize = 22;
        tb.Foreground = new SolidColorBrush(Colors.LightGray);
        tb.Margin = new Thickness(30, 30, 30, 0);
        grid.Children.Add(tb);

        //add page
        grid.Children.Add(page.Visual);

        //add footer element
        Grid footer = new Grid();
        footer.VerticalAlignment = VerticalAlignment.Bottom;
        footer.Margin = new Thickness(50, 0, 50, 30);

        TextBlock copyright = new TextBlock();
        copyright.Foreground = new SolidColorBrush(Colors.Gray);
        copyright.Text = "Copyright © My Publisher Corp 2011.";
        footer.Children.Add(copyright);

        TextBlock pgNumber = new TextBlock();
        int cnt = pageNumber + 1;
        pgNumber.Text = cnt.ToString();
        pgNumber.Foreground = new SolidColorBrush(Colors.Gray);
        pgNumber.HorizontalAlignment = HorizontalAlignment.Right;
        footer.Children.Add(pgNumber);
        grid.Children.Add(footer);

        grid.Measure(_paginator.PageSize);
        grid.Arrange(new Rect(new Point(0, 0), _paginator.PageSize));

        return new DocumentPage(grid, _paginator.PageSize, page.BleedBox, page.ContentBox);
    }

    public override Size PageSize
    {
        get { return _pageSize; }
        set { _pageSize = value; }
    }

    public override bool IsPageCountValid
    {
        get
        {
            return _paginator.IsPageCountValid;
        }
    }

    public override int PageCount
    {
        get
        {
            return _paginator.PageCount;
        }
    }

    public override IDocumentPaginatorSource Source
    {
        get
        {
            return _paginator.Source;
        }
    }
}
XAML
Copy Code
<UserControl x:Class="TestProject.TestCustomPaginator"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:Intersoft="http://intersoft.clientui.com/schemas"
    mc:Ignorable="d"
    d:DesignHeight="800" d:DesignWidth="1000">

    <Grid x:Name="LayoutRoot" Background="White">
        <Intersoft:UXFlowDocumentViewer x:Name="Viewer1">
            <Intersoft:FlowDocument>
                <Intersoft:Paragraph>
                    <Intersoft:Bold FontSize="40">
                        <Intersoft:Run >
                            Danger Of Salt
                        </Intersoft:Run>
                    </Intersoft:Bold>
                    <Intersoft:LineBreak/>
                    <Intersoft:Run FontSize="20" Foreground="#FF5D5D5D">
                        THE DEADLY SUBSTANCE YOU CAN'T LIVE WITHOUT
                    </Intersoft:Run>
                    <Intersoft:LineBreak/>
                    <Intersoft:Run FontSize="18" Foreground="Gray">
                        BY DAVE GOLOKHOV
                    </Intersoft:Run>
                </Intersoft:Paragraph>
                <Intersoft:Section LineSpacingType="OneAndHalfLines" TextAlignment="Justify" SpacingBefore="30">
                    <Intersoft:Paragraph>
                        <Intersoft:Run>
                            Spike TV's 1000 Ways To Die shows us there's many ways to go, but according to the British Medical Journal, the real serial killer sits in a shaker on almost every table in North America. Their latest study aims to encourage the United Nations to make stiffer worldwide regulations on salt usage, which happens to be second-most cost-effective way of cutting global medical costs next to controlling tobacco use.
                        </Intersoft:Run>
                    </Intersoft:Paragraph>
                    <Intersoft:Paragraph SpacingBefore="20">
                        <Intersoft:Run>
                            In the United States alone, cutting salt intake by a third would save tens of thousands of lives per year and shave $24 billion off of health care costs. Reducing the country's intake of salt could also reduce the deficit.
                        </Intersoft:Run>
                    </Intersoft:Paragraph>
                    <Intersoft:Paragraph SpacingBefore="20">
                        <Intersoft:Run>
                            The equation is fairly simple: salt intake is directly correlated to blood pressure. In turn, high blood pressure is linked to strokes and heart disease, which is the leading cause of death in developed countries.
                        </Intersoft:Run>
                    </Intersoft:Paragraph>
                    <Intersoft:Paragraph SpacingBefore="20">
                        <Intersoft:Run>
                            Sounds serious enough, but try convincing someone to trade in their salty French fries and pretzels for an abstract concept of better health down the road. The correlation between over-salting and death isn’t as direct as a gunshot or a car accident, but the science is solid: The white stuff will kill you if you’re not careful.
                        </Intersoft:Run>
                    </Intersoft:Paragraph>
                </Intersoft:Section>
            </Intersoft:FlowDocument>
        </Intersoft:UXFlowDocumentViewer>
    </Grid>
</UserControl>
CS
Copy Code
public partial class TestCustomPaginator : UserControl
{
    public TestCustomPaginator()
    {
        InitializeComponent();

        DocumentPaginator paginator = new FlowDocCustomPaginator(this.Viewer1.Document.DocumentPaginator, this.Viewer1.Document.DocumentPaginator.PageSize);
        this.Viewer1.Document.CustomPaginator = paginator;
    }
}