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.
Dim diag As New PrintDialog()
The next logical thing you would attempt would be to use the PrintDocument
method:
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:
Dim r As New Run(text)
Dim ph As New Paragraph(r)
Dim doc As New FlowDocument(ph)
doc.PagePadding = New Thickness(100)
diag.PrintDocument( _
CType(doc, IDocumentPaginatorSource).DocumentPaginator, _
printCaption)
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 = "")
Dim doc As New FlowDocument(New Paragraph(New Run(text)))
doc.PagePadding = New Thickness(100)
Dim diag As New PrintDialog()
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!