Creating XPS Documents from Visual, plus an insider look at an XPS Document

In the last article, we discussed how to generate XPS Documents from Win32 applications using the XPS Document Writer. The procedure is very simple, can you simply print whatever contents you have using GDI API. Now let’s try to generate XPS Documents from WPF (Windows Presentation Foundation) using its new API.


As lots of stuff is new, we will build a simple console application, but build step by step to illustrate what exact is involved. Starting by creating a blank C# console application using Visual Studio, here is what we will get:


using System;

using System.Collections.Generic;

using System.Text;


namespace BasicXps


    class Program


        static void Main(string[] args)






There are a few ways to create XPS Documents using XPF API, you can access the XPS Document container at stream level and build thing piece by piece, you can convert from a WPF Visual object, or your can convert from a WPF UIElement object. We will focus on the conversion from Visual approach. Let’s try to create a Visual which has a yellow rectangle and a pink ellipse as in the last example. The WPF code would be:


        static Visual CreateVisual()


            const double Inch = 96;


            DrawingVisual visual = new DrawingVisual();


            DrawingContext dc = visual.RenderOpen();


            Pen bluePen = new Pen(Brushes.Blue, 1);


            dc.DrawRectangle(Brushes.Yellow, bluePen, new Rect(Inch / 2, Inch / 2, Inch * 1.5, Inch * 1.5));


            Brush pinkBrush = new SolidColorBrush(Color.FromArgb(128, 255, 0, 255));

            Pen blackPen = new Pen(Brushes.Black, 1);


            dc.DrawEllipse(pinkBrush, blackPen, new Point(Inch * 2.25, Inch * 2), Inch * 1.25, Inch);




            return visual;



DrawingVisual is one main type of Visual supported by WPF. From a DrawingVisual, you can open a DrawingContext and draw graphics primitives into it. DrawingContext is much richer than XPS in terms of graphics primitives supported, but yet every Visual, either generated through DrawingContext or otherwise can be converted to XPS, in certain form. Here the code draws a rectangle and an ellipse. Note that the pink brush is created using Color.FromArgb(128, 255, 0, 255), 50% pink to be exact.


Classes like DrawingVisual, Pen, Brush, etc., are defined in PresentationCore assembly, which depends on WindowsBase assembly. So we need to add references to them, together with the necessary namespaces:


// Needed by CreateVisual, from WindowsBase, PresentationCore.

using System.Windows;

using System.Windows.Media;


The functionality to generate XPS Document resides in ReachFramework assembly, which depends on System.Printing assembly. So we need to add two more assembly references, together with a few more namespaces:


// Needed by VisualToXps

using System.IO.Packaging;

using System.IO;


// Need by VisualToXps, from ReachFramework, which needs System.Printing and PresentationFramework

using System.Windows.Xps.Packaging;

using System.Printing.PrintSubSystem;


The code to generate an XPS Document from a Visual is shown below:


        static void VisualToXps(string fileName, Visual visual)


            Package package = Package.Open(fileName, FileMode.Create);


                XpsDocument doc = new XpsDocument(package);


                    XpsDocumentWriter writer = XpsDocument.CreateXpsDocumentWriter(doc);











The code above first creates a container (in ZIP format). A container can contain multiple XpsDocument, only one is used here. An XpsDocument can have multiple pages. A single page is generated here because we only call XpsDocumentWriter once with a single Visual.


With two new helper functions, we can change the Main function to call both of them to finish our project:


        static void Main(string[] args)


            VisualToXps(“BasicXps.container”, CreateVisual());



Visually the container generated by this code is very similar to the one generated by the XPS Document Writer. The difference can be explained by the two different creation methods, one dragging using mouse, and the other specifying by inches in C# code.


The XPS Document generated by this code is much smaller than the one created by the XPS Document Writer, it’s only 2,496 bytes in size. The difference is mainly caused by font embedding, PrintTicket, splitting of stroking and filling, and clipping. The container is small enough that we can show everything here. Here is the list of components in the container:


  • [Content_Types].xml, 543 bytes
  • FixedDocumentSequence/FixedDocumentSequeuce_1.xaml, 168 bytes
  • FixedDocuments/FixedDocument_1.xaml, 138 bytes
  • FixedPages/FixedPage_1.xaml,
  • _rels/.rels, 308 bytes.


[Context_Types].xml specifies the syntax of the container:


<?xml version=1.0 encoding=utf-8?>

<Types xmlns=>

    <Default Extension=xaml ContentType=application/ />

    <Default Extension=rels ContentType=application/ />


        ContentType=application/ />


        ContentType=application/ />



FixedDocumentdSequence_1.xaml says it only has FixedDocument_1.xaml as its only document:


<FixedDocumentSequence xmlns=>

    <DocumentReference Source=../FixedDocuments/FixedDocument_1.xaml />



FixedDocumentd_1.xaml says it only has FixedPage_1.xaml as its only page:


<FixedDocument xmlns=>

    <PageContent Source=../FixedPages/FixedPage_1.xaml />



FixedPage_1.xaml contains the XPS representation of the Visual we are writing:


<FixedPage xmlns=


    xml:lang=en-us Width=816 Height=1056>




    <Path Stroke=#FF0000FF StrokeThickness=1 StrokeMiterLimit=10 Fill=#FFFFFF00

        Data=F0 M 48, 48 L 192, 48 192, 192 48, 192Z />

    <Path Stroke=#FF000000 StrokeThickness=1 StrokeMiterLimit=10 Fill=#80FF00FF

        Data=F0 M 336, 192 C 336, 245.02 282.27, 288 216, 288 C 149.73, 288 96, 245.02 96, 192

        C 96, 138.98 149.73, 96 216, 96 C 282.27, 96 336, 138.98 336, 192Z />



The FixedPage element is quite similar, but much simpler than the version generated by the XPS Document Writer. The major new addition is the ResourceDictionary. Common elements can be put into the resource dictionary, given a name, and then reused. In this simple case, the resource dictionary happens to be empty.


Finally, the .rels binds everything together:


<?xml version=1.0 encoding=utf-8?>

<Relationships xmlns=>

    <Relationship Type=

        Target=/FixedDocumentSequences/FixedDocumentSequence_1.xaml Id=RFBE031A033A8834A />




Comments (10)

  1. beam says:

    hello Feng Yuan

    I have one question to ask

    I don’t understand the sentence "A single page is generated here because we only call XpsDocumentWriter once with a single Visual", how to create multiple pages?


  2. Can one do the opposite?

    From a XPS file saved by Word create a XAML representation?

  3. Simon says:

    hello Feng Yuan:

    I have a question to ask you,I developed a gridview control which bind data from database using WPF technology,

    then I need to print these recordset of gridview,whether I can use PrintVisual method?

    or can I get a xps document like gridview recordset? Thx a lot!

  4. Senthil says:


     I want to convert the xaml page to Xps Document. how do i convert .

         help plz..

    Thanks in advance


  5. Hi,

    We’re adding XPS output support to our new FrameMaker-alternative "Blaze". We’re using DrawingVisual and I can’t seem to find an easy to to inject hyperlinks into a DrawingVisual? Any pointers?



  6. Ryan Bean says:


    My name is Ryan Bean. We are working on a solution to build documents programmatically. Currently our system uses an ugly PS parse hack to do the job.

    My recent research about xps/docx has been very exciting. I strongly feel it is an awesome solution and have convinced the rest of the team likewise.

    We have not been able to successfully use xps print tickets. We will have multiple page documents, where certain pairs of pages (and not all) need to duplex, while the rest will not. Duplexing is a serious challenge for our developer working on the issue. We haven’t even been able to duplex a two page document in xps yet.

    I was hoping you had some resources such as white papers, books, or even examples that we could research to resolve these obstacles we have. I look forward to hearing from you.


    Ryan Bean

  7. Sam says:

    Feng, you got an error in your sample code:

    in the function VisualToXps() you never use the parameter visual, instead you call the function CreateVisual() directly from VisualToXps().

  8. Thanks to everyone who came to my session, hope you enjoyed it. First off, instead of slides I used WPF

  9. Dating says:

    In the last article , we discussed how to generate XPS Documents from Win32 applications using the XPS Document Writer. The procedure is very simple, can you simply print whatever contents you have using