Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF: Printing FlowDocument without Print Dialog

I am writing a note-taking application in WPF, using a FlowDocument for each individual note. The app searches and filters notes by tags. I want to print all notes in the current filtered list as separate documents, and I only want to show a single Print Dialog at the beginning of the job.

I found a good print example in this thread, but it is geared toward printing a single FlowDocument, so it uses a CreateXpsDocumentWriter() overload that displays a Print Dialog.

So, here's my question: Can anyone suggest some good code for printing a FlowDocument without displaying a PrintDialog? I figure I'll display the Print Dialog at the beginning of the procedure and then loop through my notes collection to print each FlowDocument.

like image 617
David Veeneman Avatar asked Aug 28 '10 20:08

David Veeneman


1 Answers

I have rewritten my answer to this question, because I did find a better way to print a set of FlowDocuments, while showing the Print Dialog only once. The answer comes from MacDonald, Pro WPF in C# 2008 (Apress 2008) in Chapter 20 at p. 704.

My code bundles a set of Note objects into an IList called notesToPrint and gets the FlowDocument for each Note from a DocumentServices class in my app. It sets the FlowDocument boundaries to match the printer and sets a 1-inch margin. Then it prints the FlowDocument, using the document's DocumentPaginator property. Here's the code:

// Show Print Dialog
var printDialog = new PrintDialog();
var userCanceled = (printDialog.ShowDialog() == false);
if(userCanceled) return;

// Print Notes
foreach(var note in notesToPrint)
{
    // Get next FlowDocument
    var collectionFolderPath = DataStore.CollectionFolderPath;
    var noteDocument = DocumentServices.GetFlowDocument(note, collectionFolderPath) ;

    // Set the FlowDocument boundaries to match the page
    noteDocument.PageHeight = printDialog.PrintableAreaHeight;
    noteDocument.PageWidth = printDialog.PrintableAreaWidth;

    // Set margin to 1 inch
    noteDocument.PagePadding = new Thickness(96);

    // Get the FlowDocument's DocumentPaginator
    var paginatorSource = (IDocumentPaginatorSource)noteDocument;
    var paginator = paginatorSource.DocumentPaginator;

    // Print the Document
    printDialog.PrintDocument(paginator, "FS NoteMaster Document");
}

This is a pretty simple approach, with one significant limitation: It doesn't print asynchronously. To do that, you would have to perform this operation on a background thread, which is how I do it.

like image 77
David Veeneman Avatar answered Sep 18 '22 12:09

David Veeneman