[ACCEPTED]-What's the best approach to printing/reporting from WPF?-reporting

Accepted answer
Score: 43

Limitations of RDL

I originally went with RDLC/ReportViewer 41 for printing with WPF but found it very 40 limiting. Some of the limitations I found 39 were:

  • RDL could only create the most boring of reports
  • It was much more work to create a report using RDL than in straight WPF: The design tools are very primitive compared to Expression Blend and RDL deals only in tables
  • I didn't have the ability to use ControlTemplates, DataTemplates, Styles, etc
  • My report fields and columns could not effectively resize and rearrange based on data size
  • Graphics had to be imported as images - it could not be drawn or edited as vectors
  • Positioning of items required code-behind rather than data binding
  • Lack of transforms
  • Very primitive data binding

Printing directly from WPF is very easy

Because of these limitations I looked 38 into creating reports using pure WPF and 37 discovered it was really quite trivial. WPF 36 allows you to implement your own DocumentPaginator subclass 35 that can generate pages.

I developed a simple 34 DocumentPaginator subclass that takes any 33 Visual, analyzes the visual tree, and hides 32 selected elements to create each page.

DocumentPaginator details

Here 31 is what my DocumentPaginator subclass does 30 during initialization (called when first 29 PageCount is fetched, or during the first 28 GetPage() call):

  1. Scans the visual tree and makes a map of all scrolled panels inside ItemsControls
  2. Starting with the outermost, makes items in the ItemsControls invisible last to first until the Visual fits on a single page without any need to scroll. If the outermost can't be reduced enough, reduces inner panels until it succeeds or has only one item at each level. Record the set of visible items as the first page.
  3. Hide the lowest-level items that have already been shown on the first page, then make subsequent items visible until they no longer fit on the page. Record all but the last-added item as the second page.
  4. Repeat the process for all pages, storing the results in a data structure.

My DocumentPaginator's GetPage 27 method is as follows:

  1. Look up the given page number in the data structure generated during initialization
  2. Hide and show items in the visual tree as indicated in the data structure
  3. Set PageNumber and NumberOfPages attached properties so report can display page numbering
  4. Flush the Dispatcher (Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(() => {} ));) to get any background rendering tasks to complete
  5. Create a Rectangle the size of the page whose VisualBrush is the visual being printed
  6. Measure, Arrange, and UpdateLayout the rectangle, then return it

This turned out to 26 be quite simple code, and allowed me to 25 turn practically anything I could create 24 with WPF into pages and print it.

Additional reporting support

Now that 23 my paginator is working, I no longer have 22 to worry very much about whether I am creating 21 my WPF content for screen or paper. In 20 fact, often UI that I build for data entry 19 and editing also works very well for printing.

From 18 there I added a simple toolbar and some 17 code behind, resulting in a full-fledged 16 reporting system built around WPF that was 15 far more capable than RDL. My reporting 14 code can export to files, print to the printer, cut/paste 13 page images, and cut/paste data for Excel. I 12 can also switch any of my UI to "print view" with 11 a click of a checkbox to see what it will 10 look like if printed. All this in just 9 a few hundred lines of C# and XAML!

At this 8 point I think the only feature RDL has that 7 my reporting code doesn't have is the ability 6 to generate a formatted Excel spreadsheet. I 5 can see how this could be done but so far 4 there has been no need - cutting and pasting 3 the data alone has been enough.

From my experience 2 my recommendation would be to write a paginator, then 1 start using WPF itself to create your reports.

Score: 25

We had this same issue, and ended up using 6 RDLC/ReportViewer for now. There's no native 5 WPF reporting tool (that I know of) and 4 RDLC is pretty simple to use, and is free. The 3 runtime overhead for it is small (around 2 2Mb) but you must remember to distribute 1 it as it isn't part of the .NET Framework.

Score: 8
Score: 3

Take a look at PdfReports. It's a code first reporting 3 engine, which is built on top of the iTextSharp 2 and EPPlus libraries. It's compatible with 1 both .NET 3.5+ Web and Windows applications.

Score: 3

How about Scryber? It allows PDF report 2 templates to be defined using xml and bound 1 to data within your application at run time. http://scryber.codeplex.com/

Score: 2

To elaborate on Ray Burns answer, if you 2 are looking for an implementation example, see: Custom Data Grid Document Paginator

Which 1 is a great starting point.

Score: 1

I've reccently accomplished task of developing 13 own reporting system, which basically consist 12 on design enviroment and data Source manager. The 11 first task was to develop WYSWIG-like design 10 enviroment. I've done this using GDI+, without 9 even bothering about printing, as it came 8 out printing/generating print preview was 7 easiest than i expected, In general it only 6 takes to draw all things on screen to graphics 5 object of printing event.

I think that in 4 case of WPF it would be similar, so all 3 you should worry about is to display you 2 report on screen and printing would be only 1 few lines of code.

Score: 0

Without getting into a whole political discussion 3 about the future of WPF, the best option 2 we found was to wrap the ReportViewer in 1 a Windows Forms host control.


More Related questions