Printing more then one page, creation in memory XPS document and DocumentViewer customization

29 בינואר 2008

2 תגובות

[This blog was migrated. You will not be able to comment here.
The new URL of this post is http://khason.net/blog/printing-more-then-one-page-creation-in-memory-xps-document-and-documentviewer-customization/]


Today, we'll answer number of questions, regarding DocumentViewer, XPSDocument, FlowDocument and more


First question: I'm trying to display FlowDocument, by using DocumentViewer and I'm getting "FlowDocument' object cannot be added to 'DocumentViewer'. DocumentViewer supports only FixedDocument or FixedDocumentSequence documents". What to do?


First answer: DocumentViewer supports only fixed document source (one, which implements IDocumentPaginatorSource – other words supports pagination). In order to do it, we have to convert FlowDocument into FixedDocument and we can do it, by using XpsDocument and it's GetFixedDocumentSequence() method to create the page sequence.


Second question: But I do not want to save anything, I want to do it in memory. What to do?


Second answer: First load your FlowDocument by using XamlReader into IDocumentPaginatorSource (that's what we'll need for DocumentViewer)



<FlowDocument xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">

    <Paragraph>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam urna augue, semper ut, condimentum et, pharetra ac, massa. Cras tellus lacus, tristique eget, tincidunt vitae, mattis at, eros. Quisque pretium, ante at porttitor accumsan, ipsum enim laoreet tellus, sit amet aliquet felis tortor et lorem. Nullam sodales viverra sapien. Morbi leo magna, dignissim a, sollicitudin at, lacinia posuere, dui. Sed vestibulum elit a ante. Vivamus pellentesque augue sit amet enim. Pellentesque dignissim, lectus at congue elementum, augue felis vulputate ante, eu bibendum dui mauris sed magna. Cras metus dui, ullamcorper id, fermentum ornare, hendrerit non, libero. Donec blandit lorem sit amet velit. Phasellus aliquam. In vel urna sit amet lorem molestie tristique. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nulla aliquam urna sit amet enim. Integer vulputate mauris non diam. Vestibulum ac mauris. Proin porttitor adipiscing nibh. Phasellus neque. Sed sollicitudin eros in diam. Quisque accumsan, neque non volutpat semper, lectus nunc porttitor libero, at pretium purus velit eget mauris.</Paragraph>

    <Paragraph>Sed ac mauris. Nulla eu augue ut est pellentesque blandit. Phasellus non quam ac neque suscipit vehicula. Donec mauris augue, pulvinar at, vestibulum quis, vulputate et, nunc. Sed ut pede. Praesent ut justo id justo nonummy porttitor. Vivamus vitae massa sit amet massa scelerisque aliquam. Nullam ligula justo, suscipit id, sollicitudin at, pretium a, lorem. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In hac habitasse platea dictumst. In quam dui, gravida quis, congue ac, rhoncus ac, mi. Donec mattis tempor orci. Mauris ullamcorper. Donec non sem vel tortor imperdiet euismod. Morbi nec eros. Maecenas quis turpis at lorem semper ullamcorper.</Paragraph>

</FlowDocument>



using (Stream io = Assembly.GetExecutingAssembly().GetManifestResourceStream("PagePrint.text.xaml"))
            {
                IDocumentPaginatorSource text = XamlReader.Load(io) as IDocumentPaginatorSource;
                io.Close();
            }


Now, let's create Xps document in memory and load our text into it



ms = new MemoryStream();
pkg = Package.Open(ms, FileMode.Create, FileAccess.ReadWrite);


doc = new XpsDocument(pkg, CompressionOption.SuperFast);
XpsSerializationManager rsm = new XpsSerializationManager(new XpsPackagingPolicy(doc), false);
DocumentPaginator pgn = text.DocumentPaginator;
rsm.SaveAsXaml(pgn);
viewer.Document = doc.GetFixedDocumentSequence();


We got an exception: "XpsDocument URI is null. Use XpsDocument constructor that takes URI parameter." But we have no URI, we are working in memory!


Third question: What to do?


Third answer: All you have to do is to add another package with URI, that identifies our document and create XPS document, by using the new identifier. We'll add it into current code and now it'll looks as following:



ms = new MemoryStream();
pkg = Package.Open(ms, FileMode.Create, FileAccess.ReadWrite);


string pack = "pack://temp.xps";
PackageStore.AddPackage(new Uri(pack), pkg);

doc = new XpsDocument(pkg, CompressionOption.SuperFast,pack);
XpsSerializationManager rsm = new XpsSerializationManager(new XpsPackagingPolicy(doc), false);
DocumentPaginator pgn = text.DocumentPaginator;
rsm.SaveAsXaml(pgn);
viewer.Document = doc.GetFixedDocumentSequence();


Well, now it works, but we still have another questions


Forth question: How to set the page size for my document?


Forth answer: You already have DocumentPaginator, why not to use it?



ms = new MemoryStream();
pkg = Package.Open(ms, FileMode.Create, FileAccess.ReadWrite);


string pack = "pack://temp.xps";
PackageStore.AddPackage(new Uri(pack), pkg);


doc = new XpsDocument(pkg, CompressionOption.SuperFast,pack);
XpsSerializationManager rsm = new XpsSerializationManager(new XpsPackagingPolicy(doc), false);
DocumentPaginator pgn = text.DocumentPaginator;

pgn.PageSize = new Size(768, 676);

rsm.SaveAsXaml(pgn);
viewer.Document = doc.GetFixedDocumentSequence();


Well done. Now our page is 8"x6" (1 inch = 96px in default resolution). Now it almost ok, but I want to customize DocumentViewer, used to present our document


Fifth question: How to remove search field ("Type text to find…") or how to customize buttons?


Fifth answer: DocumentViewer is regular WPF control, thus in order to customize it, you should override it's default template


By default the controls looks


image


But if you'll remove <ContentControl Grid.Row="2" x:Name="PART_FindToolBarHost"/> line from the control template, you'll get rid of the search bar. Of couse, you can customize anything you want within the control template of any WPF control.


image


We done. Have a nice XPS/WPF programming.


Source code for this article

הוסף תגובה
facebook linkedin twitter email

כתיבת תגובה

האימייל לא יוצג באתר. שדות החובה מסומנים *

2 תגובות

  1. Rajeev24 באוקטובר 2008 ב 12:25

    I am creating a xps document. The document contains graphs which are nothing but horizontal and vertical lines. On the graph , waves are being drawn. While printing through XPSdocument writer, screen displays the the waves on graphs but waves are not printed on the paper. Any help on this will be greatly appreciated.

    הגב
  2. Alexey12 בנובמבר 2008 ב 7:58

    Hi, Tamir.
    Very useful post, thanks.
    I have one question.
    What about all those objects that must be closed sometime? I mean MemoryStream, Package and XpsDocument objects. I assume the client is responsible for releasing these resources. Right? Will it be sufficient for this purpose if the client just calls XpsDocument's Close() method?

    הגב