/// <summary> /// Initializes a new instance of the <see cref="DocumentPaginatorEx" /> class. /// </summary> /// <param name="document">The document.</param> /// <param name="printableArea">The printable area size.</param> /// <param name="range">The print page range.</param> public DocumentPaginatorEx(FlowDocument document, Size printableArea, PageRange range) { // Clone the source document's content into a new FlowDocument. // This is because the pagination for the printer needs to be // done differently than the pagination for the displayed page. // We print the copy, rather that the original FlowDocument. var stream = new MemoryStream(); var source = new TextRange(document.ContentStart, document.ContentEnd); source.Save(stream, DataFormats.Xaml); var documentCopy = new FlowDocument(); var dest = new TextRange(documentCopy.ContentStart, documentCopy.ContentEnd); dest.Load(stream, DataFormats.Xaml); // Ready to go on the copy of the document var paginatorSource = documentCopy as IDocumentPaginatorSource; _flowDocumentPaginator = paginatorSource.DocumentPaginator; CurrentPage = 0; TotalPrintableArea = printableArea; var height = printableArea.Height; var width = printableArea.Width; var docEx = document as FlowDocumentEx; if (docEx != null) { width -= (docEx.PrintMargin.Left + docEx.PrintMargin.Right); height -= (docEx.PrintMargin.Top + docEx.PrintMargin.Bottom); DocumentPrintMargin = docEx.PrintMargin; OriginalPrintMargin = docEx.PrintMargin; Watermark = docEx.PrintWatermark; if (Watermark != null) { Watermark.Resources = document.Resources; Watermark.DataContext = document.DataContext; Watermark.Measure(printableArea); Watermark.Arrange(new Rect(0, 0, Watermark.DesiredSize.Width, Watermark.DesiredSize.Height)); } Header = docEx.PageHeader; if (Header != null) { Header.Resources = document.Resources; Header.DataContext = document.DataContext; Header.Width = width; Header.Measure(new Size(width, double.PositiveInfinity)); Header.Height = Header.DesiredSize.Height; // These two lines attempt to fix the size as desired and make sure it is properly measured at that Header.Measure(new Size(width, Header.DesiredSize.Height)); Header.Arrange(new Rect(0, 0, Header.DesiredSize.Width, Header.DesiredSize.Height)); height -= Header.DesiredSize.Height; DocumentPrintMargin = new Thickness(DocumentPrintMargin.Left, DocumentPrintMargin.Top + Header.DesiredSize.Height, DocumentPrintMargin.Right, DocumentPrintMargin.Bottom); } Footer = docEx.PageFooter; if (Footer != null) { Footer.Resources = document.Resources; Footer.DataContext = document.DataContext; Footer.Width = width; Footer.Measure(new Size(width, double.PositiveInfinity)); Footer.Height = Footer.DesiredSize.Height; // These two lines attempt to fix the size as desired and make sure it is properly measured at that Footer.Measure(new Size(width, Footer.DesiredSize.Height)); Footer.Arrange(new Rect(0, 0, Footer.DesiredSize.Width, Footer.DesiredSize.Height)); height -= Footer.DesiredSize.Height; DocumentPrintMargin = new Thickness(DocumentPrintMargin.Left, DocumentPrintMargin.Top, DocumentPrintMargin.Right, DocumentPrintMargin.Bottom + Footer.DesiredSize.Height); } } else { DocumentPrintMargin = new Thickness(); } _flowDocumentPaginator.PageSize = new Size(width, height); _flowDocumentPaginator.ComputePageCount(); TotalPages = _flowDocumentPaginator.PageCount; Range = range; }