Printing PDF documents in WPF with a preview

6/3/2014 By Hans 0 comments

Printing PDF documents in WPF applications

It is easy to print PDF documents in a application using the standard 'PrintDialog' in .NET. How to do so is described in the print pdf from wpf article. However, the dialog being used is the standard one and is rather limited in it's functionally. It does not give you a preview either on how the document will look like when its printed and some common print options are missing.

Printing with a preview

What you may want instead is a preview of how the document will be printed on paper that is larger than the PDF document, like:

pdf-print-wpf-preview1.png

Or you may want to see what part will be printed on smaller paper, like:

pdf-print-wpf-preview2.png

Or, what will the output look like when the document is rotated to landscape and vertically centered and with automatic scaling to the printable area on the paper:

pdf-print-wpf-preview3.png

Extra print options

The preview is also useful when you want to print only one or a few pages of the document, like this:

pdf-print-wpf-preview4.png

Anyway, the extra print options like duplex printing, like shown above, should always be available to reduce the usage of paper sheets.

The WPF code sample

The code sample 'ScaledPrintingWPF' in ;PDFrasterizer.NETshows an implementation of the features above. It looks like this:

pdf-print-wpf-preview5.png

It is implemented using the following MVVM architecture:

pdf-print-wpf-mvvm.png

The XAML view

A custom print dialog as shown above is implemented in XAML and has a menu to open a PDF file. It uses bindings for all printers settings and the preview box. It also has the usual code-behind part which contains only a small amount of code.

The view controller

The bindings connects the dialog to the view controller, which has the user interface logic and interfaces to the print model.

The print model

The print model is where is starts to get more interesting, here is a list of what is does:

  • it gets a list of available printers and sets the selected one.
  • it gets a list of available paper formats and set the selected one
  • it gets a list of available paper sources and set the selected one
  • it creates a print ticket and makes any item of available to the view controller
  • it holds the opened PDF document
  • it renders the currently selected page of the PDF document, transform it according to the settings that the user has made, combines it with the printer paper and the printable area and scales it so it will fit in the preview image.
  • It presents the print ticket and a couple of other settings to the document paginator at the moment when the document is printed.
  • It passes the print progress information as delegates back to the view controller so the user can be notified on the print progress.

The document paginator

This renders the PDF document one page at the time and actually spools it to the printer queue along with the print ticket. It also notifies the print model on the progress being made.

Even more print options

Not all the possibilities of;the printer ticket are implemented in this code sample, i.e. the settings for the staple and the page-order. However this can easily be implemented by just taking the duplex setting and replicate it to any other setting you might need. The duplex is a good example for these kind of extensions.

Conclusion

Implementing a such a WPF print dialog may not be that simple as there are a couple of hurdles you run into. For example the used DocumentPaginator class, which allows you to print large documents without too much memory usage can raise the infamous "FixedPage cannot contain another FixedPage" exception. Second, getting the transformations needed to scale and position the PDF in the preview tends to have a bit of complexity.

This code sample is part of the PDFRasterizer evaluation download.