Defining where on the page the flowdocument I am printing will 'start' and 'end'
- by Sagi1981
Dear community.
I am almost done with implementing a printing functionality, but I am having trouble getting the last hurdle done with.
My problem is, that I am printing some reports, consisting of a header (with information about the person the report is about), a footer (with a page number) and the content in the middle, which is a FlowDocument. Since the flowdocuments can be fairly long, It is very possible that they will span multiple pages.
My approach is to make a custom FlowDocumentPaginator which derives from DocumentPaginator.
In there i define my header and my footer.
However, when I print my page, the flowdocument and my header and footer are on top of eachother.
So my question is plain and simple - how do I define from where and to where the flowdocument part on the pages will be placed?
here is the code from my custommade Paginator:
public class HeaderedFlowDocumentPaginator : DocumentPaginator
{
    private DocumentPaginator flowDocumentpaginator;
    public HeaderedFlowDocumentPaginator(FlowDocument document)
    {
        flowDocumentpaginator = ((IDocumentPaginatorSource) document).DocumentPaginator;
    }
    public override bool IsPageCountValid
    {
        get { return flowDocumentpaginator.IsPageCountValid; }
    }
    public override int PageCount
    {
        get { return flowDocumentpaginator.PageCount; }
    }
    public override Size PageSize
    {
        get { return flowDocumentpaginator.PageSize;  }
        set { flowDocumentpaginator.PageSize = value; }
    }
    public override IDocumentPaginatorSource Source
    {
        get { return flowDocumentpaginator.Source; }
    }
    public override DocumentPage GetPage(int pageNumber)
    {
        DocumentPage page = flowDocumentpaginator.GetPage(pageNumber);
        ContainerVisual newVisual = new ContainerVisual();
        newVisual.Children.Add(page.Visual);
        DrawingVisual header = new DrawingVisual();
        using (DrawingContext dc = header.RenderOpen())
        {
            //Header data
        }
        newVisual.Children.Add(header);
        DrawingVisual footer = new DrawingVisual();
        using (DrawingContext dc = footer.RenderOpen())
        {
            Typeface typeface = new Typeface("Trebuchet MS");
            FormattedText text = new FormattedText("Page " + (pageNumber + 1).ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, typeface, 14, Brushes.Black);
            dc.DrawText(text, new Point(page.Size.Width - 100, page.Size.Height-30));
        }
        newVisual.Children.Add(footer);
        DocumentPage newPage = new DocumentPage(newVisual);
        return newPage;
    }
}
And here is the printdialogue call:
private void btnPrint_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                PrintDialog printDialog = new PrintDialog();
                if (printDialog.ShowDialog() == true)
                {
                FlowDocument fd = new FlowDocument();
                MemoryStream stream = new MemoryStream(ASCIIEncoding.Default.GetBytes(<My string of text - RTF formatted>));
                TextRange tr = new TextRange(fd.ContentStart, fd.ContentEnd);
                tr.Load(stream, DataFormats.Rtf);
                stream.Close();
                fd.ColumnWidth = printDialog.PrintableAreaWidth;
                HeaderedFlowDocumentPaginator paginator = new HeaderedFlowDocumentPaginator(fd);
                printDialog.PrintDocument(paginator, "myReport");
            }
        }
        catch (Exception ex)
        {
            //Handle
        }
    }