Search code examples
wpfprintingflowdocument

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.


Solution

  • 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.