Running on Empty

The few things I know, I like to share.

Using FlowDocuments XAML to print XPS Documents. (Part 6)

Indroduction

This one is for you Linda and Cow-Killer.

Welcome to Part 6 of the Using FlowDocuments XAML to print XPS Documents series.  Up until now it has been impossible to use this series to create an XPS document file or display the XAML text in a document viewer.  It would be nice to be able to create a XAML template and easily insert text into the template using databinding.  Here is my solution, hope to hear your feedback.

Creating a new method to Load Xaml Strings

This method simply takes a raw XAML string and loads it into a FlowDocument, you may have seen this before in previous samples.

        public static IDocumentPaginatorSource RenderFlowDocumentTemplate(string templatePath, 

Dictionary<string, string> parameters)
        {
            string rawXamlText = "";
            using (StreamReader streamReader = File.OpenText(templatePath))
            {
                rawXamlText = streamReader.ReadToEnd();
            }

            rawXamlText = MergeParameters(parameters, rawXamlText);

            FlowDocument document = XamlReader.Load(new XmlTextReader(new StringReader(rawXamlText))) as 

FlowDocument;
           
            return document;
        }

The new parts of this method are the addition of a Dictionary of string key/value pairs and the MergeParameters method.

Merging Parameters

Since XAML is nothing more than a jazzed up XML file, we can use simple string replacements to replace items in our template with strings from our objects.

        private static string MergeParameters(Dictionary<string, string> parameters, string template)
        {
            foreach (KeyValuePair<string, string> kvp in parameters)
            {
                template = template.Replace(string.Format("[{0}]", kvp.Key), kvp.Value);
            }
            return template;
        }

Now we have a nearly completed solution to XAML template rendering, all that is left to do is create a template.

The new XAML Template

<FlowDocument xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation
     xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml>
    <Paragraph FontFamily="Arial" Margin="20">
        <TextBlock Text="&#91;TestString&#93;" FontSize="12"/>
    </Paragraph>
</FlowDocument>

Notice the inclusion of [TestString], this is essentially the “databind” we will use in the string Key/Value pair dictionary.

Using the new Key/Value pair databinding

            Dictionary<string, string> strings = new Dictionary<string,string>();
            strings.Add("TestString", "Tester");
            IDocumentPaginatorSource flowDocument =
                

XamlTemplatePrinter.RenderFlowDocumentTemplate(Path.Combine(Environment.CurrentDirectory, 

"TestTemplate.xaml"), strings);
            flowDocument.DocumentPaginator.PageSize = new Size(96 * 8.5, 96 * 11);
            PrintDialog flowPrintDialog = XamlTemplatePrinter.GetPrintDialog();
            if (flowPrintDialog == null)
                return;
            PrintQueue flowPrintQueue = flowPrintDialog.PrintQueue;
            XamlTemplatePrinter.PrintFlowDocument(flowPrintQueue, 

flowDocument.DocumentPaginator);

Conclusion

Thank you all for your comments and suggestions.  Your questions and comments are fuel for the continued success of this blog.  Please feel free to leave a comment or contact me if you have suggestions or questions.

Advertisements

May 28, 2008 - Posted by | C#, WPF, XAML, XPS

15 Comments »

  1. Hi,

    great code, do you have and example of how to display XPS document file or XAML text in a document viewer?

    Also finding it difficult to pass Rich Text dynamically to flow document, any help appreciated.

    Comment by Duffer | June 10, 2008 | Reply

  2. The document viewer itself can display XAML pretty easily. Once you have created the XAML document, just pass it to the Document Viewer.

    Comment by roecode | June 11, 2008 | Reply

  3. Can anybody please tell me where i can get xamltemplatePrinter class code?

    Thanks in advance!

    Comment by Marta | July 22, 2008 | Reply

  4. The XmlTemplatePrinter class was presented in this series. Several of the methods you will find in this series are STATIC and members of that class.

    However, nowhere did I actually specify this accept in notes.

    Comment by roecode | July 22, 2008 | Reply

  5. So is the XmlTemplatePrinter class the main class for the example (i.e. the namespace for the WPF application?) or is it a second user-defined class that simply hasn’t been displayed / mentioned explicitly?

    Comment by Colin | August 12, 2008 | Reply

  6. Pretty much place all of the static methods into the XmlTemplatePrinter class.

    Comment by roecode | August 12, 2008 | Reply

  7. I’m trying to create a Print Preview window and I’ve got a FlowDocument in a FlowDocumentScrollableViewer but the problem is one of the components I want to show as part of this document is already an XPS document.

    Is it possible to merge an XPS document back into a FlowDocument? Or does it make more sense to simply create an XPS document of the original FlowDocument, merge it with the already existing XPS document. Then how do you show the user the merged XPS document prior to printing?

    Thanks,

    John

    Comment by John | September 10, 2008 | Reply

  8. I would probably convert the XPS document to XAML then place it in my FlowDocument… Or view it in an XPS document viewer first.

    Comment by roecode | September 10, 2008 | Reply

  9. Do you have a working sample of this project you could post?

    Thank you~

    Comment by Aj | October 13, 2008 | Reply

  10. I have working examples but all are under NDA. I could write up a sample app, but do not expect it soon… too many other projects on my plate.

    Comment by roecode | October 13, 2008 | Reply

  11. Thanks a ton! Works great!

    Now I have another question…I know I can’t leave your brilliance alone. We have a long running XPS document. Do you know of something that would visually indicate to the user that this page was taking a long time possibly using a background worker or popup?

    Thanks,
    Linda

    Comment by Linda Rawson | January 22, 2009 | Reply

  12. Funny you would ask… I do have something like that. I will write up an article on the subject and post it later today.

    Comment by roecode | January 23, 2009 | Reply

  13. Why not just use the FallbackValue Property on the Binding provide a value and design the FlowDocument in Kaxaml or XamlPad…

    Comment by Sven Hecht | March 30, 2009 | Reply

  14. I am not certain what question you are trying to answer, but yup I did design some of my flowdocuments in XamlPad.

    Comment by roecode | March 30, 2009 | Reply

  15. hi reocode,
    so how we can add some images to our document,
    should we append to text tag as you explained in part 5?

    Comment by bahadır | May 22, 2011 | Reply


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: