Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF printing of multiple pages with preview

The more I read about the subject the less I understand so apologies in advance if the below seems completely off the wall.

I have a usercontrol that contains a flowdocument - a view with a corresponding viewmodel. The aim is to send this to a preview window where the user can view the document and also print it.

I lifted some code from an example at http://www.eggheadcafe.com/tutorials/aspnet/9cbb4841-8677-49e9-a3a8-46031e699b2e/wpf-printing-and-print-pr.aspx

When the below is called

Public Shared Sub PrintPreview(owner As Window, data As FormData)

        Using xpsStream As New MemoryStream()

            Using package__1 As Package = Package.Open(xpsStream, FileMode.Create, FileAccess.ReadWrite)

                Dim packageUriString As String = "memorystream://data.xps"

                Dim packageUri As New Uri(packageUriString)

                PackageStore.AddPackage(packageUri, package__1)

                Dim xpsDocument__2 As New XpsDocument(package__1, CompressionOption.Maximum, packageUriString)

                Dim writer As XpsDocumentWriter = XpsDocument.CreateXpsDocumentWriter(xpsDocument__2)

                Dim visual As New Form(data)

                Dim printTicket As New PrintTicket()

                printTicket.PageMediaSize = A4PaperSize

                writer.Write(visual, printTicket)

                Dim document As FixedDocumentSequence = xpsDocument__2.GetFixedDocumentSequence()

                xpsDocument__2.Close()

                Dim printPreviewWnd As New PrintPreviewWindow(document)

                printPreviewWnd.Owner = owner

                printPreviewWnd.ShowDialog()

                PackageStore.RemovePackage(packageUri)

            End Using
        End Using

This brings up the print preview window and shows the user control that holds the flowdocument. However, it only shows the first of what should be multiple pages. I was under the assumption the whole point of writing the xps and then reading it back again in this window was to work around the problem of printing a visual but I'm obviously misunderstanding the whole process. Any help in getting through my thick head what I need to do to be able to view all of the pages in the document would be much appreciated.

Cheers

I thought the above with using xpsdocument and getfixeddocumentsequence would convert the flowdocument to a fixeddocument but seeing it doesn't, am I perhaps writing it wrongly??

like image 690
c95mbq Avatar asked Apr 04 '11 00:04

c95mbq


1 Answers

You can print a visual to an XPS. However, as I understand it, it is your job to manage pages. If your visual is too big to fit on a page, you need to find a way to split it onto multiple pages.

The source code I posted here prints a list of items over many pages:

https://bitbucket.org/paulstovell/samples/src/a323f0c65ea4/XPS%20Report%20Generator/

If you can find a way to split your visuals (perhaps create 3 forms, with 15 items per form) into pages, you can then use this:

using (var doc = new XpsDocument("P:\\Test2.xps", FileAccess.Write))
{
    var writer = XpsDocument.CreateXpsDocumentWriter(doc);
    var collator = writer.CreateVisualsCollator();

    collator.BeginBatchWrite();
    collator.Write(form1);
    collator.Write(form2);
    collator.Write(form3);
    collator.EndBatchWrite();
}

var doc2 = new XpsDocument("P:\\Test2.xps", FileAccess.Read);

var seq = doc2.GetFixedDocumentSequence();

var window = new Window();
window.Content = new DocumentViewer {Document = seq};
window.ShowDialog();

Also, note that if you're newing up a visual and printing it, you'll need to size it first, otherwise you may get an empty screen. Here's an example of generating a page of data (of course you'd change the sizes to fit an A4 sheet).

private StackPanel CreatePage()
{
    var panel = new StackPanel();
    panel.Width = 1000;
    panel.Height = 1000;

    for (var i = 0; i < 10; i++)
    {
        panel.Children.Add(new TextBlock() {Text = "Item " + i});
    }

    panel.Measure(new Size(1000, 1000));
    panel.Arrange(new Rect(0, 0, 1000, 1000));

    return panel;
}
like image 153
Paul Stovell Avatar answered Oct 02 '22 21:10

Paul Stovell