Tag Archives: WPF Printing

Printing in WPF

NOTE: I have released a new version of this library. Please follow this link: WPF Printing Library v2.0

Printing? All of my programmer friends hate writing code that does printing. It is quite complicated to write this. Thinking of problems about aligning, font size, pagination is quite fraught.
In WPF printing is a bit easier, you can print everything you see on the screen doing following:

<StackPanel Name="printingStackPanel>
<TextBlock Grid.Row="0" Grid.Column="1" FontSize="20"
             VerticalAlignment="Center" Foreground="White"
             HorizontalAlignment="Center" Text="{Binding Path=HsNummer.Benennung}"
<TextDecoration PenThicknessUnit="FontRecommended">
          <Pen Thickness="1.5">
<LinearGradientBrush Opacity="0.5" StartPoint="0,0.5" EndPoint="1,0.5">
<GradientStop Color="White" Offset="0" />
<GradientStop Color="Lime" Offset="0.5" />
<GradientStop Color="White" Offset="1" />
  <Button Content=This is my Button/>

Printing this piece of XAML is done following:

private void PrintClick(object sender, RoutedEventArgs e)
PrintDialog dialog = new PrintDialog();
    if (dialog.ShowDialog() == true)
dialog.PrintVisual(printingStackPanel "printingStackPanel");

So this is the easy way of printing. A slightly more difficult way of printing is, if you want to add on each page a header, footer, some details that are only visible on the first or last page or if you want to add page count numbers, etc.
For this reason I began to implement a printing library that will work only referencing the 3 standard WPF Libraries:

  1. PresentationFramework
  2. PresentationCore
  3. WindowsBase

The main parts used for printing can be coded using plain C# or using WPF. It does not matter what kind is used. In this tutorial I will especially focus on the plain C# method, because this is the one that I mainly use.

First of all, I will answer the question why I have developed such a library!

The reason is, because in the company I work in, I had to develop an administrative program, including printing of invoices and delivery reports. Now you can maybe imagine what the major problem was. The invoice may contain a very large amount of items such that they do not fit on one DIN-A4. Therefore all other items have to be printed on a new page. But what is the problem? Using plain XAML and embedding all items in a ListBox and printing it I risk the problem of truncating an item in the middle. The other problem is that you cannot specify any footer nor any header. Well, the header can printed on the first page, I agree, and the footer on the bottom of the last page, but what if you want to print a footer and/or header on every single page? That is not possible.

So, that is the reason I decided to do what I have done.

What can be done until now using this library?

  1. Printing footer/header/recipient on every single page
  2. Printing the page count on every page
  3. Decide what has to be printed: e.g. header and no footer, no page count
  4. Print a new item on a new page if there is not enough page available
  5. Printing a customizable summary of all items at the end of the report

What are the drawbacks?

  1. If an item is longer than the available space for printing items you will get an infinite loop.
  2. According standards of WPF, that a control is created only in the main thread, you cannot print in background(I will check that and try to fix it)
  3. Impossible to print to OneNote and XPS.
  4. Until now not possible to decide whether the footer is printed only on the last page according to that you also cannot decide whether a header is printed only on the first page. (It’s just on my To-do list)

I want to check and fix these drawbacks in the near future if I have time available.

Class Library

Actually the library consists of 7 classes, only 6 of public interest. The remaining one is the main class that coordinates the whole printing progress and has no public accessors.
The class of your major interest ist the PrintProcessor. But for better understanding how this class will work I will explain the PrintDimension and the enum PrintAppendixes earlier.


The PrintAppendixes is a flag-enum that defines the parts that have to be printed. Here you can set up if you want to print only the page footer, page header, footer and header or all other possible combinations of all values.
As you certainly know, flag enums can be joined. That means you can select only one value but also more of them by applying it with the binary operator |.

<span >e.g.
PrintAppendixes pa = PrintAppendixes.Header | PrintAppendixes.Footer;

In that example you have to set the PrintAppendix in such a way that the printer will print additional to the page data also the header and the footer of the page.


The next class that is of interest, ist the PrintDimension class. It provides all necessary information to paginate the document.

As you can see this class provides some properties. Not for all of them necessarily a value has to be set. This depends on the PrintAppendix parameter that you pass to it’s constructor. If you pass the value of the example shown above you are forced to set the FooterHeight and the HeaderHeight. This value is used to positioning each element on the page. With that values you can define the height that has to be used for printing the particular data. But if you want to set a value to SummaryHeight you will get an error saying that according to the passed PrintAppendixes you cannot set this value. If you want to set the SummaryHeight you have to set the PrintAppendixes flag to Summary. Additionally to the error catching in setting the values there is an other error catching during the print process if you set a value in the enum and do not provide a corresponding height value for that value. As you can see the PrintDimension class provides three different Construcors. I will shortly show what each of those constructors call.

  • PrintDimension() : this(PrintAppendixes.None)
  • PrintDimension(PrintAppendixes pa) : this(pa,new Thickness(50,25,50,50)
  • PrintDimension(PrintAppendixes pa, Thickness margin)

The parameter of type Thickness is used to specify what is the space that should be free on the page. The value new Thickness(50,25,50,50) set as default should be the optimal for printing on a printer.

PrintAppendixes pa = PrintAppendixes.Header | PrintAppendixes.Footer;
PrintingDimensions pd = new PrintingDimensions(pa);
pd.FooterHeight = 30;
pd.HeaderHeight = 30;
pd.SummaryHeight = 30; //throws following exception: InvalidOperationException("You have to set the SummaryHeight before printing if the PrintAppendixes flag has set to "Summary"."))


<span >
Now I will speak about the class of major interest, the PrintProcessor class.

It is an abstract class that provides all the necessary information and data that has to be printed. As you can see in the class diagram on the left hand side all inherited classes have to implement the following methods/properties:

  • GetNextItem()
  • GetTable()
  • PrintDimensions
  • >FileName

All other methods are marked as virtual and can be overwritten if desired. But there is one constraint. You are forced to pass a PrintingDimension to the base class and as you have seen before that you have to set in PrintDimension a valid value for the PrintAppendix and corresponding to that a valid value for each dimension you have to overwrite the corresponding GetMethod. If you will not overwrite each corresponding method to each value set in the PrintAppendix flag enum you will get in that moment an exception when you try to print.

As you can not see in the class diagram all of the GetMethods that are not italic are marked as virtual. As just said you have to overwrite them if you set the corresponding PrintAppendix flag, otherwise the trial of printing will rise an error. As you can se the return type is always UIElement, that means you can specify by yourself the element that has to be returned.

Note that the element which is returned by any of that methods will be printed on the document.

Note: If you set the PrintAppendix flag to PrintAppendix.Header and you will not overwrite the GetHeader() method you cannot print the document. In this case, if the PrintAppendix flag for the footer is not set, do not be surprised if the GetFooter() method is not called. Only those, depending on the flag set, are executed.

Now I will get in the description of the GetNextItem() method. This method is marked as abstract therefore you have to provide it. According to the name of the method this method should provide the item that has to be printed in the body. The return type of that method is of type ILineItem that provides the line itself and the height of the line. The method is called as long as you provide values. In the case when this method return null, the printer considers to have finished printing all line items.

public class MyCustomPrintProcessor : PrintProcessor
    private int _no = 0;
public MyCustomPrintProcessor(PrintingDimensions pd) :base(pd)
public override UIElement GetFooter()
        return new Label { Content = "This is the footer" };
public override UIElement GetHeader()
        return new Label { Content = "This is the header" };
public override UIElement GetSummary()
return new Label { Content = "This is the summary an will never be called because of the Summary flag is not set in PrintDimensions" };
public override ILineItem GetNextItem()
        if(_no == 10)
            return null;
return new MyCustomLineItem(int ++_no);


The interface ILineItem provides the method GetLine() that returns the content of each single line and the property LineHeight. Until now (January 2011) you have to set the height of the returning line manually, but in further releases of this printing library I will provide the automatic calculation of the item. The LineHeight is used to position the element in the document body. Furthermore it is used to check whether the element has to be printed on a new page or not.

NOTE: until now (January 2011) you will get into troubles if the Height is higher than the total space available for printing.

public MyCustomLineItem : ILineItem
private readonly int _i;
public MyCustonLineItem(int i)
        _i = i;
public UIElementGetLine()
return new Label {Content = "This is item #"+i};
public double LineHeight
        get { return 20;}


As you might have seen in the PrintProcessor class there is a GetBackgroud() method that provides the background of the document. The class provides only methods for positioning the background on the document and the background element, of that the opacity can be set.

Example C# project for printing

You can download a complete working “Visual Studio 2010 solution” that demonstrate my printing library by using this link: MmPrinting20100117.

NOTE: please change the file format of the downloading document from *.docx to* .rar

The class diagram can be downloaded here: Class library.

NOTE: I have released a new version of this library. Please follow this link: WPF Printing Library v2.0


Posted by on January 17, 2011 in C-Sharp, Printing, WPF


Tags: , ,