Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

WPF Printing - Basic Text Printing

0.00/5 (No votes)
17 Feb 2009 1  
This articles teaches you how to perform basic text printing in WPF.

Introduction

This article demonstrates how to perform basic text printing in WPF.

To skip the article and just get to the code, see the "Complete and simplified printing routine" below.

Background

Recently, I created my first WPF application. It was a very simple application. All it did was process some data and then print a report. Well, the code for processing the data was standard; however, trying to figure out the code for printing a simple report drove me crazy! I searched around the internet for some examples (and found some), but didn't really find what I was looking for, which was something simple and quick. So, I started to wonder if simple printing was even supported in WPF. After a little bit of playing around, I found out that it is!

Printing is not only supported in WPF, it is vastly more powerful than Windows Forms printing (believe it or not). Microsoft actually invested quite a bit of time, and made some great improvements when they designed the printing model for WPF. The only drawback is that it is a little more convoluted.

Since my main goal was just to do some real basic printing, such as: do some processing and send a text report to the printer, that's what this article will demonstrate.

Printing text using the PrintDialog.PrintDocument method

First, let's create some text to print:

Dim text As String = "Print this text"

Second, let's create the print caption: this is the text that will appear in the Windows print queue when you open up the printer and look at the print jobs. It only appears while the job is printing.

Dim printCaption As String = "My first print job."

The next thing we need to do to perform simple printing is to create a new instance of the PrintDialog class. This class can not only be used to display a print dialog box for the user to be able to select a printer and modify printer options, it can also be used to actually perform the printing, even if you decide to not show the print dialog box.

'Used to perform printing
Dim diag As New PrintDialog()  

The next logical thing you would attempt would be to use the PrintDocument method:

'Send the document to the printer
diag.PrintDocument(text, printCaption) 

However, you'll quickly find the PrintDocument will not work this way. The PrintDocument method takes a DocumentPaginator (System.Windows.Documents.DocumentPaginator). Since the DocumentPaginator is a "Must Inherit" (abstract) class, you cannot create a new instance of it. So, where in the world do we get one? Good question...

This is where it gets a little convoluted (as I mentioned)... The FlowDocument (System.Windows.Documents.FlowDocument) is a class that can be used to store and format the text that we want to print. Although the FlowDocument class is not a DocumentPaginator, it implements the IDocumentPaginatorSource.DocumentPaginator interface, which provides access to its DocumentPaginator!

Unfortunately, the FlowDocument class constructor does not just take text (a String) as an argument, it takes a Block (System.Windows.Documents.Block), which, conveniently, is another "Must Inherit" (abstract) class. Because the Paragraph class (System.Windows.Documents.Paragraph) inherits the Block class, it can be used as the argument instead.

The Paragraph class constructor is similar to the FlowDocument class constructor in that it does not take text (a String) as an argument. Instead, the Paragraph class constructor takes an Inline class as an argument, which conveniently enough (again), is another "Must Inherit" (abstract) class. Because the Run class (System.Windows.Documents.Run) inherits the Inline class, it can be used as the argument instead.

So having said all that, let's take a look at what the rest of code looks like:

'Create a new Run class, passing it the text.
' The Run class contains 1 line of text
Dim r As New Run(text)

'Create a new paragraph, passing it the new run class instance
Dim ph As New Paragraph(r)

'Create the document, passing a new paragraph
Dim doc As New FlowDocument(ph)
doc.PagePadding = New Thickness(100) 'Creates margin around the page

'Send the document to the printer
diag.PrintDocument( _
    CType(doc, IDocumentPaginatorSource).DocumentPaginator, _
    printCaption)

Complete and simplified printing routine

Now that we know how to program the printing, let's condense it and put it all together in a sub routine that can be called to perform the printing:

Private Sub PrintUsingDocumentCondensed(ByVal text As String, _
        Optional ByVal printCaption As String = "")

    'Create the document, passing a new paragraph and new run using text
    Dim doc As New FlowDocument(New Paragraph(New Run(text)))
    doc.PagePadding = New Thickness(100) 'Creates margin around the page

    Dim diag As New PrintDialog() 'Used to perform printing

    'Send the document to the printer
    diag.PrintDocument( _
        CType(doc, IDocumentPaginatorSource).DocumentPaginator, _
        printCaption)

End Sub

Finally, to actually perform our printing:

PrintUsingDocumentCondensed("Print this text", "My first print job")

Conclusion

As you can see, printing basic text in WPF is pretty easy!

I've included a source code demo for you, which was created with Visual Basic in Visual Studio 2008.

Hopefully, this article will be helpful for you!

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here