[WPF] Génération d'un document XPS multipage

Génération d'un document XPS multipage en WPF

Préambule

Ce tutoriel va présenter la génération de documents XPS multipages.
Nous allons voir comment générer un document multipages sous diverses formats (A0 ... A10, etc...)
La plupart des standards connus sont intégrés (la source contient 2 standards de plus que la version papier).

Le tutoriel est très simple. La seule chose qui soit longue est la création des standards...

Introduction

Lorsque nous développons une application, il arrive parfois que l'on ait besoin de faire des impressions de nos contrôles présents à l'écran ou pour tout autre chose.

Dans le projet que je réécris en WPF, l'utilisateur doit placer les produits que le magasin vend sur les rayons de sorte que les afficheurs digitaux affichent les bonnes informations. Il me fallait donc laisser à l'utilisateur le choix de garder une trace physique de ces informations. Utilisant WPF, il m'est apparu facile de générer ce document imprimable en XPS. Nous verrons comment générer un fichier xps de manière « standard » et une autre manière plus abouti.

Génération d'un document XPS par les classes de base

WPF fournit quelques classes pour la génération de documents XPS. Nous avons :

  • Package : ouvre un flux utilisable par XpsDocument.
  • XpsDocument : Permet de créer le document XPS.
  • XpsDocumentWriter : Permet d'écrire les objets dans le document XPS.

Ecrire des objets dans le document XPS est extrêmement simple avec cette méthode, voici un exemple :

static public void WriteVisuals(string filename, IEnumerable<Visual> visuals)
{
    Package package = FileStream.Open(filename, FileMode.Create, FileAccess.Write);
    XpsDocument xDoc = new XpsDocument(package);
    XpsDocumentWriter writer = XpsDocument.CreateXpsDocumentWriter(xDoc);
    foreach(Visual visual in visuals)
        writer.Write(visual);
    package.Close();
}

Comme vous le voyez, il s'agit d'une méthode simple, on ouvre un package avec le nom du fichier passé en paramètre. Ensuite on crée le document XPS et enfin on le remplit.

Simple et rapide, n'est-ce pas ? Cependant, mes essais m'ont conduit à un grave problème : le fichier généré est toujours d'une page.

Mes recherches m'ont conduit à créer le multipage de manière manuelle. Ce que j'ai donc fait mais avec des modifications bienvenues.

Génération de documents XPS multipages

Dans cette partie, nous allons créer notre document en multipages en utilisant un FixedDocument. Le seul inconvénient de cette classe est que l'on ne peut pas choisir l'emplacement de rendu de ses objets. Néanmoins avec ce que nous allons voir, il s'agit d'un moindre mal.

En premier lieu créons une bibliothèque de classes nommé XpsGenerator.

Une fois cela fait, cliquez-droit sur `References' et ajoutez ces assemblies :

ReachFramework
System.Printing
Ces deux assemblies vont nous permettre d'avoir accès à l'espace de noms Xps.

Puis ajoutez aussi cette assembly pour pouvoir avoir accès aux classes FixedDocument, DocumentViewer et UIElement.

WindowsBase
PresentationCore
PresentationFramework

Maintenant lorsque nous allons vouloir imprimer nos fichiers il pourrait être utile de choisir la « taille » du papier à savoir A0, A1, ..., A10. Et pour pouvoir choisir une taille définie à la feuille (par exemple 101 mm x 23 cm), il faudrait que nous puissions avoir une routine qui calcule le nombre de pixels à notre place. Commençons donc :

En premier, nous allons créer un fichier qui contiendra juste une propriété permettant de connaitre la valeur de calcul. (Cette valeur sera représentée en pixels).

Nommez ce fichier RenderFormat et remplissez-le comme ceci :

namespace XpsGenerator
{
    /// <summary>
    /// Format to render.
    /// </summary>
    sealed public class RenderFormat
    {
        #region Property
        /// <summary>
        /// Gets the value of the rendered format.
        /// </summary>
        public double Value
        {
            get;
            private set;
        }
        #endregion

        #region Constructor
        /// <summary>
        /// Instantiates a new rendering format.
        /// </summary>
        /// <param name="value">Value of the format.</param>
        internal RenderFormat(double value)
        {
            Value = value;
        }
        #endregion
    }
}

Ensuite, créez un fichier RenderFormats qui contiendra les propriétés de RenderFormat que nous aurons définis :

Pixel : Contient la valeur d'un pixel
Inch : Contient la valeur d'un pouce (en pixels)
Centimeter : Contient la valeur d'un centimètre (en pixel)
Millimeter : Contient la valeur d'un millimètre (en pixel)
Point : Contient la valeur d'un point (en pixel)
Un pixel aura la valeur par défaut 1.

Un pouce aura la valeur par défaut 96. (un pouce = 96 pixels)

Un centimètre aura la valeur par défaut 37.7952.... (un centimètre = 96 / 2.54 pixels)

Un millimètre aura la valeur par défaut 3.77952... (un millimètre = 1 / 10 cm)

Un point aura la valeur par défaut 1.33 (un point = 96 / 72 pixels)

Ces valeurs peuvent être trouvées sur la MSDN ici

Le fichier est donc rempli comme ceci :

namespace XpsGenerator
{
    /// <summary>
    /// Represents a list of rendered format.
    /// </summary>
    static public class RenderFormats
    {
        #region Fields
        /// <summary>
        /// Represents a pixel.
        /// </summary>
        static private readonly RenderFormat pixel;

        /// <summary>
        /// Represents an inch.
        /// </summary>
        static private readonly RenderFormat inch;

        /// <summary>
        /// Represents a centimeter.
        /// </summary>
        static private readonly RenderFormat centimeter;

        /// <summary>
        /// Represents a point.
        /// </summary>
        static private readonly RenderFormat point;

        /// <summary>
        /// Represents a milimeter.
        /// </summary>
        static private readonly RenderFormat milimeter;
        #endregion

        #region Properties
        /// <summary>
        /// Gets the format of a pixel. (1 px)
        /// </summary>
        static public RenderFormat Pixel
        {
            get { return pixel; }
        }

        /// <summary>
        /// Gets the format of an inch. (1in = 96 px)
        /// </summary>
        static public RenderFormat Inch
        {
            get { return inch; }
        }

        /// <summary>
        /// Gets the format of a centimeter. (1cm = 96.0 / 2.54 px)
        /// </summary>
        static public RenderFormat Centimeter
        {
            get { return centimeter; }
        }

        /// <summary>
        /// Gets the format of a milimeter. (1mm = 0.1 cm)
        /// </summary>
        static public RenderFormat Milimeter
        {
            get { return milimeter; }
        }

        /// <summary>
        /// Gets the format of a point. (1pt = 96.0 / 72.0 px)
        /// </summary>
        static public RenderFormat Point
        {
            get { return point; }
        }
        #endregion

        #region Constructor
        /// <summary>
        /// Instantiates each format.
        /// </summary>
        static RenderFormats()
        {
            pixel = new RenderFormat(1.0);
            inch = new RenderFormat(96.0);
            centimeter = new RenderFormat(96.0 / 2.54);
            milimeter = new RenderFormat(0.1 * (96.0 / 2.54));
            point = new RenderFormat(96.0 / 72.0);
        }
        #endregion
    }
}

A présent que nous avons nos « convertisseurs » nous pouvons nous atteler à la création de nos feuilles. Nos feuilles pourront être rendues de 2 façons :

Portrait
Paysage

Créez donc un nouveau fichier nommé SheetOrientation et remplissez-le comme ceci :

namespace XpsGenerator
{
    /// <summary>
    /// Orientation of the sheet.
    /// </summary>
    public enum SheetOrientation
    {
        /// <summary>
        /// Portrait orientation.
        /// </summary>
        Portrait,

        /// <summary>
        /// Landscape orientation.
        /// </summary>
        Landscape
    }
}

Ensuite nous allons créer nos feuilles. Pour cela, il nous faudra créer une classe SheetFormat, qui contiendra une propriété Width de type double représentant la longueur de notre feuille, et une propriété Height de type double représentant la hauteur de notre feuille. Pour plus de flexibilité le constructeur est laissé en type publique, dès fois qu'il y'ait besoin d'imprimer des objets sur des feuilles non standardisés.

Maintenant, créez un fichier SheetFormat et remplissez-le comme ceci :

namespace XpsGenerator
{
    /// <summary>
    /// Represents a format of a sheet.
    /// </summary>
    sealed public class SheetFormat
    {
        #region Properties
        /// <summary>
        /// Gets the width of the sheet. 
        /// </summary>
        public double Width
        {
            get;
            private set;
        }

        /// <summary>
        /// Gets the height of the sheet.

        /// </summary>
        public double Height
        {
            get;
            private set;
        }
        #endregion

        #region Constructor
        /// <summary>
        /// Instantiates a new sheet format.
        /// </summary>
        /// <param name="width">Width of the sheet.</param>
        /// <param name="height">Height of the sheet.</param>
        /// <param name="heightRenderFormat">RenderFormat to use for the height of the sheet.</param>
        /// <param name="widthRenderFormat">RenderFormat to use for the width of the sheet.</param>
        public SheetFormat(double width, double height, RenderFormat widthRenderFormat, RenderFormat heightRenderFormat)
        {
            Width = width * widthRenderFormat.Value;
            Height = height * heightRenderFormat.Value;
        }

        /// <summary>
        /// Instantiates a new sheet format.
        /// </summary>
        /// <param name="width">Width of the sheet.</param>
        /// <param name="height">Height of the sheet.</param>
        /// <param name="renderFormat">RenderFormat to use for width and height of the sheet.</param>
        public SheetFormat(double width, double height, RenderFormat renderFormat)
        : this(width, height, renderFormat, renderFormat)
        { }

        /// <summary>
        /// Instantiates a new sheet format.
        /// The rendering format is in milimeter mode.
        /// </summary>
        /// <param name="width">Width of the sheet.</param>
        /// <param name="height">Height of the sheet.</param>
        public SheetFormat(double width, double height)
        : this(width, height, RenderFormats.Milimeter)
        { }
        #endregion
    }
}

Ici, nous restons flexible nous autorisons la création de feuilles dont la largeur et la hauteur souhaité ne sont pas dans le même format. Nous autorisons aussi la création de feuilles dont les dimensions ont le même format et enfin nous autorisons la création de feuilles au format millimétré.

Un avantage certain, lorsque nous souhaiterons imprimer nos feuilles en utilisant des rames standards (A3, A4, A5, ...), serait de posséder en interne les formats de fichiers standards.

Ce tableau les récapitule (ici, seulement les classes A à E sont représentées au format millimétré):

CLASSE A CLASSE B CLASSE C CLASSE D CLASSE E
0 841 x 1189 1000 x 1414 917 x 1297
1 594 x 841 707 x 1000 648 x 917 779 x 545
2 420 x 594 500 x 707 458 x 648 545 x 385
3 297 x 420 353 x 500 324 x 458 385 x 272 560 x 400
4 210 x 297 250 x 353 229 x 324 272 x 192 400 x 280
5 148 x 210 176 x 250 126 x 229 192 x 136 280 x 200
6 105 x 148 125 x 176 114 x 126 136 x 96 200 x 140
7 74 x 105 88 x 125 81 x 114 96 x 78
8 52 x 74 62 x 88 57 x 81
9 37 x 52 44 x 62 40 x 57
10 26 x 37 31 x 44 28 x 40

Pour ceux qui voudraient un peu plus d'informations sur cette standardisation, allez voir ici.

Maintenant créez un fichier SheetFormats qui contiendra toutes les standardisations fournit par Wikipédia. (De la classe A à la classe E, puis les normes françaises et Américaines).

Le fichier devient donc :

namespace XpsGenerator
{
    /// <summary>
    /// Represents the normalized sheet format in each class.
    /// </summary>
    static public class SheetFormats
    {
        /// <summary>
        /// Represents the sheet format in the A class. (Standard A4 = 210 x 297 mm)
        /// </summary>
        static public class ClassA
        {
            #region Fields
            /// <summary>
            /// Represents the size of the A0 sheet.
            /// </summary>
            static private readonly SheetFormat _A0;

            /// <summary>
            /// Represents the size of the A1 sheet.
            /// </summary>
            static private readonly SheetFormat _A1;

            /// <summary>
            /// Represents the size of the A2 sheet.
            /// </summary>
            static private readonly SheetFormat _A2;

            /// <summary>
            /// Represents the size of the A3 sheet.
            /// </summary>
            static private readonly SheetFormat _A3;

            /// <summary>
            /// Represents the size of the A4 sheet.
            /// </summary>
            static private readonly SheetFormat _A4;

            /// <summary>
            /// Represents the size of the A5 sheet.
            /// </summary>
            static private readonly SheetFormat _A5;

            /// <summary>
            /// Represents the size of the A6 sheet.
            /// </summary>
            static private readonly SheetFormat _A6;

            /// <summary>
            /// Represents the size of the A7 sheet.
            /// </summary>
            static private readonly SheetFormat _A7;

            /// <summary>
            /// Represents the size of the A8 sheet.
            /// </summary>
            static private readonly SheetFormat _A8;

            /// <summary>
            /// Represents the size of the A9 sheet.
            /// </summary>
            static private readonly SheetFormat _A9;

            /// <summary>
            /// Represents the size of the A10 sheet.
            /// </summary>
            static private readonly SheetFormat _A10;
            #endregion

            #region Properties
            /// <summary>
            /// Gets the size of the A0 sheet. (481 x 1189 mm)
            /// </summary>
            static public SheetFormat A0
            {
                get { return _A0; }
            }

            /// <summary>
            /// Gets the size of the A1 sheet. (594 x 481 mm)
            /// </summary>
            static public SheetFormat A1
            {
                get { return _A1; }
            }

            /// <summary>
            /// Gets the size of the A2 sheet. (420 x 594 mm)
            /// </summary>
            static public SheetFormat A2
            {
                get { return _A2; }
            }

            /// <summary>
            /// Gets the size of the A3 sheet. (297 x 420 mm)
            /// </summary>
            static public SheetFormat A3
            {
                get { return _A3; }
            }

            /// <summary>
            /// Gets the size of the A0 sheet. (210 x 297 mm)
            /// </summary>
            static public SheetFormat A4
            {
                get { return _A4; }
            }

            /// <summary>
            /// Gets the size of the A0 sheet. (148 x 210 mm)
            /// </summary>
            static public SheetFormat A5
            {
                get { return _A5; }
            }

            /// <summary>
            /// Gets the size of the A0 sheet. (105 x 148 mm)
            /// </summary>
            static public SheetFormat A6
            {
                get { return _A6; }
            }

            /// <summary>
            /// Gets the size of the A0 sheet. (74 x 105 mm)
            /// </summary>
            static public SheetFormat A7
            {
                get { return _A7; }
            }

            /// <summary>
            /// Gets the size of the A0 sheet. (52 x 74 mm)
            /// </summary>
            static public SheetFormat A8
            {
                get { return _A8; }
            }

            /// <summary>
            /// Gets the size of the A0 sheet. (37 x 52 mm)
            /// </summary>
            static public SheetFormat A9
            {
                get { return _A9; }
            }

            /// <summary>
            /// Gets the size of the A0 sheet. (26 x 37 mm)
            /// </summary>
            static public SheetFormat A10
            {
                get { return _A10; }
            }
            #endregion

            #region Constructor
            /// <summary>
            /// Instantiates each sheet.
            /// </summary>
            static ClassA()
            {
                _A0 = new SheetFormat(841, 1189);
                _A1 = new SheetFormat(594, 841);
                _A2 = new SheetFormat(420, 594);
                _A3 = new SheetFormat(297, 420);
                _A4 = new SheetFormat(210, 297);
                _A5 = new SheetFormat(148, 210);
                _A6 = new SheetFormat(105, 148);
                _A7 = new SheetFormat(74, 105);
                _A8 = new SheetFormat(52, 74);
                _A9 = new SheetFormat(37, 52);
                _A10 = new SheetFormat(26, 37);
            }
            #endregion
        }

        /// <summary>
        /// Represents the sheet format in the B class. (Standard A4 = 250 x 353 mm)
        /// </summary>
        static public class ClassB
        {
            #region Fields
            /// <summary>
            /// Represents the size of the B0 sheet.
            /// </summary>
            static private readonly SheetFormat _B0;

            /// <summary>
            /// Represents the size of the B1 sheet.
            /// </summary>
            static private readonly SheetFormat _B1;

            /// <summary>
            /// Represents the size of the B2 sheet.
            /// </summary>
            static private readonly SheetFormat _B2;

            /// <summary>
            /// Represents the size of the B3 sheet.
            /// </summary>
            static private readonly SheetFormat _B3;

            /// <summary>
            /// Represents the size of the B4 sheet.
            /// </summary>
            static private readonly SheetFormat _B4;

            /// <summary>
            /// Represents the size of the B5 sheet.
            /// </summary>
            static private readonly SheetFormat _B5;

            /// <summary>
            /// Represents the size of the B6 sheet.
            /// </summary>
            static private readonly SheetFormat _B6;

            /// <summary>
            /// Represents the size of the B7 sheet.
            /// </summary>
            static private readonly SheetFormat _B7;

            /// <summary>
            /// Represents the size of the B8 sheet.
            /// </summary>
            static private readonly SheetFormat _B8;

            /// <summary>
            /// Represents the size of the B9 sheet.
            /// </summary>
            static private readonly SheetFormat _B9;

            /// <summary>
            /// Represents the size of the B10 sheet.
            /// </summary>
            static private readonly SheetFormat _B10;
            #endregion

            #region Properties
            /// <summary>
            /// Gets the size of the B0 sheet. (1000 x 1414 mm)
            /// </summary>
            static public SheetFormat B0
            {
                get { return _B0; }
            }

            /// <summary>
            /// Gets the size of the B1 sheet. (707 x 1000 mm)
            /// </summary>
            static public SheetFormat B1
            {
                get { return _B1; }
            }

            /// <summary>
            /// Gets the size of the B2 sheet. (500 x 707 mm)
            /// </summary>
            static public SheetFormat B2
            {
                get { return _B2; }
            }

            /// <summary>
            /// Gets the size of the B3 sheet. (353 x 500 mm)
            /// </summary>
            static public SheetFormat B3
            {
                get { return _B3; }
            }

            /// <summary>
            /// Gets the size of the B4 sheet. (250 x 353 mm)
            /// </summary>
            static public SheetFormat B4
            {
                get { return _B4; }
            }

            /// <summary>
            /// Gets the size of the B5 sheet. (176 x 250 mm)
            /// </summary>
            static public SheetFormat B5
            {
                get { return _B5; }
            }

            /// <summary>
            /// Gets the size of the B6 sheet. (125 x 176 mm)
            /// </summary>
            static public SheetFormat B6
            {
                get { return _B6; }
            }

            /// <summary>
            /// Gets the size of the B7 sheet. (88 x 125 mm)
            /// </summary>
            static public SheetFormat B7
            {
                get { return _B7; }
            }

            /// <summary>
            /// Gets the size of the B8 sheet. (62 x 88 mm)
            /// </summary>
            static public SheetFormat B8
            {
                get { return _B8; }
            }

            /// <summary>
            /// Gets the size of the B9 sheet. (44 x 62 mm)
            /// </summary>
            static public SheetFormat B9
            {
                get { return _B9; }
            }

            /// <summary>
            /// Gets the size of the B10 sheet. (31 x 44 mm)
            /// </summary>
            static public SheetFormat B10
            {
                get { return _B10; }
            }
            #endregion

            #region Constructor
            /// <summary>
            /// Instantiates each sheet.
            /// </summary>
            static ClassB()
            {
                _B0 = new SheetFormat(1000, 1414);
                _B1 = new SheetFormat(707, 1000);
                _B2 = new SheetFormat(500, 707);
                _B3 = new SheetFormat(353, 500);
                _B4 = new SheetFormat(250, 353);
                _B5 = new SheetFormat(176, 250);
                _B6 = new SheetFormat(125, 176);
                _B7 = new SheetFormat(88, 125);
                _B8 = new SheetFormat(62, 88);
                _B9 = new SheetFormat(44, 62);
                _B10 = new SheetFormat(31, 44);
            }
            #endregion
        }

        /// <summary>
        /// Represents the sheet format in the C class. (Standard A4 = 229 x 324 mm)
        /// </summary>
        static public class ClassC
        {
            #region Fields
            /// <summary>
            /// Represents the size of the C0 sheet.
            /// </summary>
            static private readonly SheetFormat _C0;

            /// <summary>
            /// Represents the size of the C1 sheet.
            /// </summary>
            static private readonly SheetFormat _C1;

            /// <summary>
            /// Represents the size of the C2 sheet.
            /// </summary>
            static private readonly SheetFormat _C2;

            /// <summary>
            /// Represents the size of the C3 sheet.
            /// </summary>
            static private readonly SheetFormat _C3;

            /// <summary>
            /// Represents the size of the C4 sheet.
            /// </summary>
            static private readonly SheetFormat _C4;

            /// <summary>
            /// Represents the size of the C5 sheet.
            /// </summary>
            static private readonly SheetFormat _C5;

            /// <summary>
            /// Represents the size of the C6 sheet.
            /// </summary>
            static private readonly SheetFormat _C6;

            /// <summary>
            /// Represents the size of the C7 sheet.
            /// </summary>
            static private readonly SheetFormat _C7;

            /// <summary>
            /// Represents the size of the C8 sheet.
            /// </summary>
            static private readonly SheetFormat _C8;

            /// <summary>
            /// Represents the size of the C9 sheet.
            /// </summary>
            static private readonly SheetFormat _C9;

            /// <summary>
            /// Represents the size of the C10 sheet.
            /// </summary>
            static private readonly SheetFormat _C10;
            #endregion

            #region Properties
            /// <summary>
            /// Gets the size of the C0 sheet. (917 x 1297 mm)
            /// </summary>
            static public SheetFormat C0
            {
                get { return _C0; }
            }

            /// <summary>
            /// Gets the size of the C1 sheet. (648 x 917 mm)
            /// </summary>
            static public SheetFormat C1
            {
                get { return _C1; }
            }

            /// <summary>
            /// Gets the size of the C2 sheet. (458 x 648 mm)
            /// </summary>
            static public SheetFormat C2
            {
                get { return _C2; }
            }

            /// <summary>
            /// Gets the size of the C3 sheet. (324 x 458 mm)
            /// </summary>
            static public SheetFormat C3
            {
                get { return _C3; }
            }

            /// <summary>
            /// Gets the size of the C4 sheet. (229 x 324 mm)
            /// </summary>
            static public SheetFormat C4
            {
                get { return _C4; }
            }

            /// <summary>
            /// Gets the size of the C5 sheet. (162 x 229 mm)
            /// </summary>
            static public SheetFormat C5
            {
                get { return _C5; }
            }

            /// <summary>
            /// Gets the size of the C6 sheet. (114 x 162 mm)
            /// </summary>
            static public SheetFormat C6
            {
                get { return _C6; }
            }

            /// <summary>
            /// Gets the size of the C7 sheet. (81 x 114 mm)
            /// </summary>
            static public SheetFormat C7
            {
                get { return _C7; }
            }

            /// <summary>
            /// Gets the size of the C8 sheet. (57 x 81 mm)
            /// </summary>
            static public SheetFormat C8
            {
                get { return _C8; }
            }

            /// <summary>
            /// Gets the size of the C9 sheet. (40 x 57 mm)
            /// </summary>
            static public SheetFormat C9
            {
                get { return _C9; }
            }

            /// <summary>
            /// Gets the size of the C10 sheet. (28 x 40 mm)
            /// </summary>
            static public SheetFormat C10
            {
                get { return _C10; }
            }
            #endregion

            #region Constructor
            /// <summary>
            /// Instantiates each sheet.
            /// </summary>
            static ClassC()
            {
                _C0 = new SheetFormat(917, 1297);
                _C1 = new SheetFormat(648, 917);
                _C2 = new SheetFormat(458, 648);
                _C3 = new SheetFormat(324, 458);
                _C4 = new SheetFormat(229, 324);
                _C5 = new SheetFormat(162, 229);
                _C6 = new SheetFormat(114, 162);
                _C7 = new SheetFormat(81, 114);
                _C8 = new SheetFormat(57, 81);
                _C9 = new SheetFormat(40, 57);
                _C10 = new SheetFormat(28, 40);
            }
            #endregion
        }

        /// <summary>
        /// Represents the sheet format in the D class. (Standard A4 = 229 x 324 mm)
        /// </summary>
        static public class ClassD
        {
            #region Fields
            /// <summary>
            /// Represents the size of the D1 sheet.
            /// </summary>
            static private readonly SheetFormat _D1;

            /// <summary>
            /// Represents the size of the D2 sheet.
            /// </summary>
            static private readonly SheetFormat _D2;

            /// <summary>
            /// Represents the size of the D3 sheet.
            /// </summary>
            static private readonly SheetFormat _D3;

            /// <summary>
            /// Represents the size of the D4 sheet.
            /// </summary>
            static private readonly SheetFormat _D4;

            /// <summary>
            /// Represents the size of the D5 sheet.
            /// </summary>
            static private readonly SheetFormat _D5;

            /// <summary>
            /// Represents the size of the D6 sheet.
            /// </summary>
            static private readonly SheetFormat _D6;

            /// <summary>
            /// Represents the size of the D7 sheet.
            /// </summary>
            static private readonly SheetFormat _D7;
            #endregion

            #region Properties
            /// <summary>
            /// Gets the size of the D1 sheet. (648 x 917 mm)
            /// </summary>
            static public SheetFormat D1
            {
                get { return _D1; }
            }

            /// <summary>
            /// Gets the size of the D2 sheet. (458 x 648 mm)
            /// </summary>
            static public SheetFormat D2
            {
                get { return _D2; }
            }

            /// <summary>
            /// Gets the size of the D3 sheet. (324 x 458 mm)
            /// </summary>
            static public SheetFormat D3
            {
                get { return _D3; }
            }

            /// <summary>
            /// Gets the size of the D4 sheet. (229 x 324 mm)
            /// </summary>
            static public SheetFormat D4
            {
                get { return _D4; }
            }

            /// <summary>
            /// Gets the size of the D5 sheet. (162 x 229 mm)
            /// </summary>
            static public SheetFormat D5
            {
                get { return _D5; }
            }

            /// <summary>
            /// Gets the size of the D6 sheet. (114 x 162 mm)
            /// </summary>
            static public SheetFormat D6
            {
                get { return _D6; }
            }

            /// <summary>
            /// Gets the size of the D7 sheet. (81 x 114 mm)
            /// </summary>
            static public SheetFormat D7
            {
                get { return _D7; }
            }
            #endregion

            #region Constructor
            /// <summary>
            /// Instantiates each sheet.
            /// </summary>
            static ClassD()
            {
                _D1 = new SheetFormat(779, 545);
                _D2 = new SheetFormat(545, 385);
                _D3 = new SheetFormat(385, 272);
                _D4 = new SheetFormat(272, 192);
                _D5 = new SheetFormat(192, 136);
                _D6 = new SheetFormat(136, 96);
                _D7 = new SheetFormat(96, 72);
            }
            #endregion
        }

        /// <summary>
        /// Represents the sheet format in the E class. (Standard A4 = 229 x 324 mm)
        /// </summary>
        static public class ClassE
        {
            #region Fields
            /// <summary>
            /// Represents the size of the E3 sheet.
            /// </summary>
            static private readonly SheetFormat _E3;

            /// <summary>
            /// Represents the size of the E4 sheet.
            /// </summary>
            static private readonly SheetFormat _E4;

            /// <summary>
            /// Represents the size of the E5 sheet.
            /// </summary>
            static private readonly SheetFormat _E5;

            /// <summary>
            /// Represents the size of the E6 sheet.
            /// </summary>
            static private readonly SheetFormat _E6;
            #endregion

            #region Properties
            /// <summary>
            /// Gets the size of the E3 sheet. (324 x 458 mm)
            /// </summary>
            static public SheetFormat E3
            {
                get { return _E3; }
            }

            /// <summary>
            /// Gets the size of the E4 sheet. (229 x 324 mm)
            /// </summary>
            static public SheetFormat E4
            {
                get { return _E4; }
            }

            /// <summary>
            /// Gets the size of the E5 sheet. (162 x 229 mm)
            /// </summary>
            static public SheetFormat E5
            {
                get { return _E5; }
            }

            /// <summary>
            /// Gets the size of the E6 sheet. (114 x 162 mm)
            /// </summary>
            static public SheetFormat E6
            {
                get { return _E6; }
            }
            #endregion

            #region Constructor
            /// <summary>
            /// Instantiates each sheet.
            /// </summary>
            static ClassE()
            {
                _E3 = new SheetFormat(560, 400);
                _E4 = new SheetFormat(400, 280);
                _E5 = new SheetFormat(280, 200);
                _E6 = new SheetFormat(200, 140);
            }
            #endregion
        }

        /// <summary>
        /// Represents the american format of the sheet.
        /// </summary>
        static public class AmericanFormat
        {
            #region Fields
            /// <summary>
            /// Represents the size of the Quarto sheet.
            /// </summary>
            static private readonly SheetFormat _Quarto;

            /// <summary>
            /// Represents the size of the Foolscap sheet.
            /// </summary>
            static private readonly SheetFormat _Foolscap;

            /// <summary>
            /// Represents the size of the Executive sheet.
            /// </summary>
            static private readonly SheetFormat _Executive;

            /// <summary>
            /// Represents the size of the Government-Letter sheet.
            /// </summary>
            static private readonly SheetFormat _GovernmentLetter;

            /// <summary>
            /// Represents the size of the Letter sheet.
            /// </summary>
            static private readonly SheetFormat _Letter;

            /// <summary>
            /// Represents the size of the Legal sheet.
            /// </summary>
            static private readonly SheetFormat _Legal;

            /// <summary>
            /// Represents the size of the Tabloid sheet.
            /// </summary>
            static private readonly SheetFormat _Tabloid;

            /// <summary>
            /// Represents the size of the Post sheet.
            /// </summary>
            static private readonly SheetFormat _Post;

            /// <summary>
            /// Represents the size of the Crown sheet.
            /// </summary>
            static private readonly SheetFormat _Crown;

            /// <summary>
            /// Represents the size of the Large Post sheet.
            /// </summary>
            static private readonly SheetFormat _LargePost;

            /// <summary>
            /// Represents the size of the Demy sheet.
            /// </summary>
            static private readonly SheetFormat _Demy;

            /// <summary>
            /// Represents the size of the Medium sheet.
            /// </summary>
            static private readonly SheetFormat _Medium;

            /// <summary>
            /// Represents the size of the Royal sheet.
            /// </summary>
            static private readonly SheetFormat _Royal;

            /// <summary>
            /// Represents the size of the Elephant sheet.
            /// </summary>
            static private readonly SheetFormat _Elephant;

            /// <summary>
            /// Represents the size of the Double Demy sheet.
            /// </summary>
            static private readonly SheetFormat _DoubleDemy;

            /// <summary>
            /// Represents the size of the Quad Demy sheet.
            /// </summary>
            static private readonly SheetFormat _QuadDemy;

            /// <summary>
            /// Represents the size of the STMT sheet.
            /// </summary>
            static private readonly SheetFormat _STMT;

            /// <summary>
            /// Represents the size of the A sheet.
            /// </summary>
            static private readonly SheetFormat _A;

            /// <summary>
            /// Represents the size of the B sheet.
            /// </summary>
            static private readonly SheetFormat _B;

            /// <summary>
            /// Represents the size of the C sheet.
            /// </summary>
            static private readonly SheetFormat _C;

            /// <summary>
            /// Represents the size of the D sheet.
            /// </summary>
            static private readonly SheetFormat _D;

            /// <summary>
            /// Represents the size of the E sheet.
            /// </summary>
            static private readonly SheetFormat _E;
            #endregion

            #region Properties
            /// <summary>
            /// Gets the size of the Quarto sheet. (254 x 203 mm)
            /// </summary>
            static public SheetFormat Quarto
            {
                get { return _Quarto; }
            }

            /// <summary>
            /// Gets the size of the Foolscap sheet. (330 x 203 mm)
            /// </summary>
            static public SheetFormat Foolscap
            {
                get { return _Foolscap; }
            }

            /// <summary>
            /// Gets the size of the Executive sheet. (267 x 184 mm)
            /// </summary>
            static public SheetFormat Executive
            {
                get { return _Executive; }
            }

            /// <summary>
            /// Gets the size of the Government letter sheet. (267 x 203 mm)
            /// </summary>
            static public SheetFormat GovernmentLetter
            {
                get { return _GovernmentLetter; }
            }

            /// <summary>
            /// Gets the size of the Letter sheet. (279 x 216 mm)
            /// </summary>
            static public SheetFormat Letter
            {
                get { return _Letter; }
            }

            /// <summary>
            /// Gets the size of the Legal sheet. (356 x 216 mm)
            /// </summary>
            static public SheetFormat Legal
            {
                get { return _Legal; }
            }

            /// <summary>
            /// Gets the size of the Tabloid sheet. (432 x 279 mm)
            /// </summary>
            static public SheetFormat Tabloid
            {
                get { return _Tabloid; }
            }

            /// <summary>
            /// Gets the size of the Post sheet. (489 x 394 mm)
            /// </summary>
            static public SheetFormat Post
            {
                get { return _Post; }
            }

            /// <summary>
            /// Gets the size of the Crown sheet. (508 x 381 mm)
            /// </summary>
            static public SheetFormat Crown
            {
                get { return _Crown; }
            }

            /// <summary>
            /// Gets the size of the Large Post sheet. (533 x 419 mm)
            /// </summary>
            static public SheetFormat LargePost
            {
                get { return _LargePost; }
            }

            /// <summary>
            /// Gets the size of the Demy sheet. (572 x 445 mm)
            /// </summary>
            static public SheetFormat Demy
            {
                get { return _Demy; }
            }

            /// <summary>
            /// Gets the size of the Medium sheet. (584 x 457 mm)
            /// </summary>
            static public SheetFormat Medium
            {
                get { return _Medium; }
            }

            /// <summary>
            /// Gets the size of the Royal sheet. (635 x 508 mm)
            /// </summary>
            static public SheetFormat Royal
            {
                get { return _Royal; }
            }

            /// <summary>
            /// Gets the size of the Elephant sheet. (711 x 584 mm)
            /// </summary>
            static public SheetFormat Elephant
            {
                get { return _Elephant; }
            }

            /// <summary>
            /// Gets the size of the Double Demy sheet. (889 x 597 mm)
            /// </summary>
            static public SheetFormat DoubleDemy
            {
                get { return _DoubleDemy; }
            }

            /// <summary>
            /// Gets the size of the Quad Demy sheet. (1143 x 889 mm)
            /// </summary>
            static public SheetFormat QuadDemy
            {
                get { return _QuadDemy; }
            }

            /// <summary>
            /// Gets the size of the STMT sheet. (216 x 140 mm)
            /// </summary>
            static public SheetFormat STMT
            {
                get { return _STMT; }
            }

            /// <summary>
            /// Gets the size of the A sheet. (279 x 216 mm)
            /// </summary>
            static public SheetFormat A
            {
                get { return _A; }
            }

            /// <summary>
            /// Gets the size of the B sheet. (432 x 279 mm)
            /// </summary>
            static public SheetFormat B
            {
                get { return _B; }
            }

            /// <summary>
            /// Gets the size of the C sheet. (559 x 432 mm)
            /// </summary>
            static public SheetFormat C
            {
                get { return _C; }
            }

            /// <summary>
            /// Gets the size of the D sheet. (864 x 559 mm)
            /// </summary>
            static public SheetFormat D
            {
                get { return _D; }
            }

            /// <summary>
            /// Gets the size of the E sheet. (1118 x 864 mm)
            /// </summary>
            static public SheetFormat E
            {
                get { return _E; }
            }
            #endregion

            #region Constructor
            /// <summary>
            /// Instantiates each sheet.
            /// </summary>
            static AmericanFormat()
            {
                _Quarto = new SheetFormat(254, 203);
                _Foolscap = new SheetFormat(330, 203);
                _Executive = new SheetFormat(267, 184);
                _GovernmentLetter = new SheetFormat(267, 203);
                _Letter = new SheetFormat(279, 216);
                _Legal = new SheetFormat(356, 216);
                _Tabloid = new SheetFormat(432, 279);
                _Post = new SheetFormat(489, 394);
                _Crown = new SheetFormat(508, 381);
                _LargePost = new SheetFormat(533, 419);
                _Demy = new SheetFormat(572, 445);
                _Medium = new SheetFormat(584, 457);
                _Royal = new SheetFormat(635, 508);
                _Elephant = new SheetFormat(711, 584);
                _DoubleDemy = new SheetFormat(889, 597);
                _QuadDemy = new SheetFormat(1143, 889);
                _STMT = new SheetFormat(216, 140);
                _A = new SheetFormat(279, 216);
                _B = new SheetFormat(432, 279);
                _C = new SheetFormat(559, 432);
                _D = new SheetFormat(864, 559);
                _E = new SheetFormat(1118, 864);
            }
            #endregion
        }

        /// <summary>
        /// Represents the french format of the sheet.
        /// </summary>
        static public class FrenchFormat
        {
            #region Fields
            /// <summary>
            /// Represents the size of the Bell sheet.
            /// </summary>
            static private readonly SheetFormat _Bell;

            /// <summary>
            /// Represents the size of the SchoolBoy sheet.
            /// </summary>
            static private readonly SheetFormat _SchoolBoy;

            /// <summary>
            /// Represents the size of the Foolscap sheet.
            /// </summary>
            static private readonly SheetFormat _Foolscap;

            /// <summary>
            /// Represents the size of the Crown writing sheet.
            /// </summary>
            static private readonly SheetFormat _CrownWriting;

            /// <summary>
            /// Represents the size of the Crown publishing sheet.
            /// </summary>
            static private readonly SheetFormat _CrownPublishing;

            /// <summary>
            /// Represents the size of the Roberto sheet.
            /// </summary>
            static private readonly SheetFormat _Roberto;

            /// <summary>
            /// Represents the size of the Ecu sheet.
            /// </summary>
            static private readonly SheetFormat _Ecu;

            /// <summary>
            /// Represents the size of the _Sheel sheet.
            /// </summary>
            static private readonly SheetFormat _Shell;

            /// <summary>
            /// Represents the size of the _Square sheet.
            /// </summary>
            static private readonly SheetFormat _Square;

            /// <summary>
            /// Represents the size of the Rider sheet.
            /// </summary>
            static private readonly SheetFormat _Rider;

            /// <summary>
            /// Represents the size of the Half grap sheet.
            /// </summary>
            static private readonly SheetFormat _HalfGrap;

            /// <summary>
            /// Represents the size of the Grap sheet.
            /// </summary>
            static private readonly SheetFormat _Grap;

            /// <summary>
            /// Represents the size of the Double grap sheet.
            /// </summary>
            static private readonly SheetFormat _DoubleGrap;

            /// <summary>
            /// Represents the size of the Jesus sheet.
            /// </summary>
            static private readonly SheetFormat _Jesus;

            /// <summary>
            /// Represents the size of the Sun sheet.
            /// </summary>
            static private readonly SheetFormat _Sun;

            /// <summary>
            /// Represents the size of the Pigeon shows sheet.
            /// </summary>
            static private readonly SheetFormat _PigeonShows;

            /// <summary>
            /// Represents the size of the Dove commercial sheet.
            /// </summary>
            static private readonly SheetFormat _DoveCommercial;

            /// <summary>
            /// Represents the size of the Little eagle sheet.
            /// </summary>
            static private readonly SheetFormat _LittleEagle;

            /// <summary>
            /// Represents the size of the Eagle sheet.
            /// </summary>
            static private readonly SheetFormat _Eagle;

            /// <summary>
            /// Represents the size of the Big world sheet.
            /// </summary>
            static private readonly SheetFormat _BigWorld;

            /// <summary>
            /// Represents the size of the Universe sheet.
            /// </summary>
            static private readonly SheetFormat _Universe;
            #endregion

            #region Properties
            /// <summary>
            /// Gets the size of the Bell sheet. (300 x 400 mm)
            /// </summary>
            static public SheetFormat Bell
            {
                get { return _Bell; }
            }

            /// <summary>
            /// Gets the size of the SchoolBoy sheet. (310 x 400 mm)
            /// </summary>
            static public SheetFormat SchoolBoy
            {
                get { return _SchoolBoy; }
            }

            /// <summary>
            /// Gets the size of the SchoolBoy sheet. (340 x 440 mm)
            /// </summary>
            static public SheetFormat Foolscap
            {
                get { return _Foolscap; }
            }

            /// <summary>
            /// Gets the size of the Crown writing sheet. (340 x 440 mm)
            /// </summary>
            static public SheetFormat CrownWriting
            {
                get { return _CrownWriting; }
            }

            /// <summary>
            /// Gets the size of the Crown publishing sheet. (370 x 470 mm)
            /// </summary>
            static public SheetFormat CrownPublishing
            {
                get { return _CrownPublishing; }
            }

            /// <summary>
            /// Gets the size of the Roberto sheet. (390 x 500 mm)
            /// </summary>
            static public SheetFormat Roberto
            {
                get { return _Roberto; }
            }

            /// <summary>
            /// Gets the size of the Ecu sheet. (400 x 520 mm)
            /// </summary>
            static public SheetFormat Ecu
            {
                get { return _Ecu; }
            }

            /// <summary>
            /// Gets the size of the Shell sheet. (440 x 560 mm)
            /// </summary>
            static public SheetFormat Shell
            {
                get { return _Shell; }
            }

            /// <summary>
            /// Gets the size of the Square sheet. (450 x 560 mm)
            /// </summary>
            static public SheetFormat Square
            {
                get { return _Square; }
            }

            /// <summary>
            /// Gets the size of the Rider sheet. (460 x 620 mm)
            /// </summary>
            static public SheetFormat Rider
            {
                get { return _Rider; }
            }

            /// <summary>
            /// Gets the size of the Half grap sheet. (325 x 500 mm)
            /// </summary>
            static public SheetFormat HalfGrap
            {
                get { return _HalfGrap; }
            }

            /// <summary>
            /// Gets the size of the Grap sheet. (500 x 650 mm)
            /// </summary>
            static public SheetFormat Grap
            {
                get { return _Grap; }
            }

            /// <summary>
            /// Gets the size of the Double grap sheet. (650 x 1000 mm)
            /// </summary>
            static public SheetFormat DoubleGrap
            {
                get { return _DoubleGrap; }
            }

            /// <summary>
            /// Gets the size of the Jesus sheet. (560 x 760 mm)
            /// </summary>
            static public SheetFormat Jesus
            {
                get { return _Jesus; }
            }

            /// <summary>
            /// Gets the size of the Sun sheet. (600 x 800 mm)
            /// </summary>
            static public SheetFormat Sun
            {
                get { return _Sun; }
            }

            /// <summary>
            /// Gets the size of the Pigeon shows sheet. (600 x 800 mm)
            /// </summary>
            static public SheetFormat PigeonShows
            {
                get { return _PigeonShows; }
            }

            /// <summary>
            /// Gets the size of the Dove commercial sheet. (630 x 900 mm)
            /// </summary>
            static public SheetFormat DoveCommercial
            {
                get { return _DoveCommercial; }
            }

            /// <summary>
            /// Gets the size of the Little eagle sheet. (700 x 940 mm)
            /// </summary>
            static public SheetFormat LittleEagle
            {
                get { return _Ecu; }
            }

            /// <summary>
            /// Gets the size of the Eagle sheet. (750 x 1060 mm)
            /// </summary>
            static public SheetFormat Eagle
            {
                get { return _Eagle; }
            }

            /// <summary>
            /// Gets the size of the Big world sheet. (900 x 1260 mm)
            /// </summary>
            static public SheetFormat BigWorld
            {
                get { return _BigWorld; }
            }

            /// <summary>
            /// Gets the size of the Universe sheet. (1000 x 1300 mm)
            /// </summary>
            static public SheetFormat Universe
            {
                get { return _Universe; }
            }
            #endregion

            #region Constructor
            /// <summary>
            /// Instantiates the french format sheet.
            /// </summary>
            static FrenchFormat()
            {
                _Bell = new SheetFormat(300, 400);
                _SchoolBoy = new SheetFormat(310, 400);
                _Foolscap = new SheetFormat(340, 440);
                _CrownWriting = new SheetFormat(360, 460);
                _CrownPublishing = new SheetFormat(370, 470);
                _Roberto = new SheetFormat(390, 500);
                _Ecu = new SheetFormat(400, 520);
                _Shell = new SheetFormat(440, 560);
                _Square = new SheetFormat(450, 560);
                _Rider = new SheetFormat(460, 620);
                _HalfGrap = new SheetFormat(325, 500);
                _Grap = new SheetFormat(500, 650);
                _DoubleGrap = new SheetFormat(650, 1000);
                _Jesus = new SheetFormat(560, 760);
                _Sun = new SheetFormat(600, 800);
                _PigeonShows = new SheetFormat(600, 800);
                _DoveCommercial = new SheetFormat(630, 900);
                _LittleEagle = new SheetFormat(700, 940);
                _Eagle = new SheetFormat(750, 1060);
                _BigWorld = new SheetFormat(900, 1260);
                _Universe = new SheetFormat(1000, 1300);
            }
            #endregion
        }
    }
}

Tadaa, très long mais au moins on a une bonne base pour la création de documents.

La dernière étape consiste à écrire une classe permettant de générer un document xps multipages. Exceptionnellement simple grâce à la classe FixedDocument.

Créez un ultime fichier nommé FixedDocumentHelper.

Ajoutez-y les directives suivantes :

#region USING Directives
using System;
using System.IO;
using System.IO.Packaging;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Markup;
using System.Windows.Xps;
using System.Windows.Xps.Packaging;
#endregion

Ensuite dans la classe (qualifiez-là aussi de sealed), créez une variable locale nommée fixedDocument de type FixedDocument.

#region Fields
/// <summary>
/// Represents the document to use to store our multipages.
/// </summary>
private FixedDocument fixedDocument;
#endregion

Ensuite créez le constructeur instanciant ce document.

#region Constructor
/// <summary>
/// Instantiates the fixed document.
/// </summary>
public FixedDocumentHelper()
{
    fixedDocument = new FixedDocument();
}
#endregion

Ensuite nous allons créer diverses méthodes pour ajouter nos pages dans le document. Comment allons-nous ajouter nos objets dans la feuille ? En premier on doit définir la taille de la feuille puis sa méthode de rendu (pixel, pouce, centimètre, millimètre et point), puis l'objet UIElement à injecter dans la feuille. Un fixed document prend en « paramètre » un PageContent. Le PageContent prendra en « paramètre » un FixedPage. Et ce FixedPage ne peut avoir en contenu qu'un type UIElement.

En premier lieu il faut créer notre PageContent puis notre FixedPAge. Ensuite on met en page la taille de la FixedPage créée en manipulant ses propriétés Width et Height.

Ensuite nous ajoutons notre contenu dans le fixedpage, puis nous ajoutons notrefixed page dans notre pageContent et enfin nous ajoutons notre pageContent dans le fixed document.

Attention on n'ajoute pas un contenu dans un PageContent comme ça, il faut passer par un cast explicite en IAddChild.

Donc dans notre code, cela donne :

/// <summary>
/// Add a page into the fixed document.
/// </summary>
/// <param name="width">Width of the page.</param>
/// <param name="height">Height of the page.</param>
/// <param name="renderFormatWidth">Device to use to render the width of the page.</param>
/// <param name="renderFormatHeight">Device to use to render the height of the page.</param>
/// <param name="contentPage">UI element to add as content of the page.</param>
public void AddPage(double width, double height, RenderFormat renderFormatWidth, RenderFormat renderFormatHeight, UIElement contentPage)
{
    PageContent pageContent = new PageContent();
    FixedPage fixedPage = new FixedPage();
    fixedPage.Width = width * renderFormatWidth.Value;
    fixedPage.Height = height * renderFormatHeight.Value;
    fixedPage.Children.Add(contentPage);
    ((IAddChild)pageContent).AddChild(fixedPage);
    fixedDocument.Pages.Add(pageContent);
}

Maintenant il nous faut une autre méthode qui uniformisera le format de rendu pour la hauteur et la largeur du document.

/// <summary>
/// Add a page into the fixed document.
/// </summary>
/// <param name="width">Width of the page.</param>
/// <param name="height">Height of the page.</param>
/// <param name="renderFormat">Device to use to render the width and the height of the page.</param>
/// <param name="contentPage">UI element to add as content of the page.</param>
public void AddPage(double width, double height, RenderFormat renderFormat, UIElement contentPage)
{
    PageContent pageContent = new PageContent();
    FixedPage fixedPage = new FixedPage();
    fixedPage.Width = width * renderFormat.Value;
    fixedPage.Height = height * renderFormat.Value;
    fixedPage.Children.Add(contentPage);
    ((IAddChild)pageContent).AddChild(fixedPage);
    fixedDocument.Pages.Add(pageContent);
}

C'est proche d'être bon mais on ne s'est quand même pas tapé du boulot pour rien en créant les formats de feuilles, qu'à cela ne tienne et ajoutons-y cette méthode :

/// <summary>
/// Add a page into the fixed document.
/// </summary>
/// <param name="format">Format of the sheet to use.</param>
/// <param name="orientation">Orientation of the sheet.</param>
/// <param name="contentPage">UI element to add as content of the page.</param>
public void AddPage(SheetFormat format, SheetOrientation orientation, UIElement contentPage)
{
    PageContent pageContent = new PageContent();
    FixedPage fixedPage = new FixedPage();
    fixedPage.Width = orientation == SheetOrientation.Portrait ? format.Width : format.Height;
    fixedPage.Height = orientation == SheetOrientation.Portrait ? format.Height : format.Width;
    fixedPage.Children.Add(contentPage);
    ((IAddChild)pageContent).AddChild(fixedPage);
    fixedDocument.Pages.Add(pageContent);
}

Puis pour terminer l'ajout on va créer une méthode qui fournira l'orientation Portrait par défaut.

/// <summary>
/// Add a page into the fixed document.
/// The default orientation is portrait.
/// </summary>
/// <param name="format">Format of the sheet.</param>
/// <param name="element">UI element to add as content page.</param>
public void AddPage(SheetFormat format,
UIElement contentPage)
{
    AddPage(format, SheetOrientation.Portrait, contentPage);
}

Les seules choses qui nous restent à faire à présent est de sauvegarder le document au format XPS et de charger le dit document dans un document viewer.

Pour la sauvegarde, il faut reprendre la 1ère méthode, sauf qu'au lieu de lui envoyer des Visuals on lui envoie notre fixed document nouvellement créé.

/// <summary>
/// Save the fixed document into an xps file.
/// </summary>
/// <param name="filename">Name of the xps document.</param>
public void SaveToXps(string filename)
{
    Package pkg = Package.Open(filename, FileMode.Create);
    XpsDocument doc = new XpsDocument(pkg);
    XpsDocumentWriter writer = XpsDocument.CreateXpsDocumentWriter(doc);
    writer.Write(fixedDocument);
    doc.Close();
    pkg.Close();
}

Et enfin notre méthode de chargement (qualifiez-là de statique car le chargement se fait en interne). La seule astuce est de créer un XpsDocument avec en paramètre le nom du fichier, et ensuite de passer la séquence du document à la propriété Document du document viewer.

/// <summary>
/// Load the specified xps document and send it into the document viewer.
/// </summary>
/// <param name="filename">Name of the file to load.</param>
/// <param name="documentViewer">Container of the loaded file.</param>
/// <exception cref="System.Exception">Occurs when the filename isn't an xps file.</exception>
static public void ShowGeneratedDocument(string filename, ref DocumentViewer documentViewer)
{
    if (Path.GetExtension(filename) != ".xps")
        throw new Exception("Error !! The filename need to be a xps file.");

    XpsDocument xpsDoc = new XpsDocument(filename, FileAccess.Read);
    documentViewer.Document = xpsDoc.GetFixedDocumentSequence();
    xpsDoc.Close();
    documentViewer.Focus();
}

Conclusion

Et voilà, ce tutorial s'achève. Nous avons vu comment générer un fichier XPS et comment créer nos pages en suivant un modèle de format standard et qui peut être orienté.

Le seul défaut de cette technique est que nous utilisons un FixedDocument ne nous permettant pas de positionner nos objets comme nous le voulons. Néanmoins cette méthode reste très appréciable lorsque nous ignorons combien d'objets nous devons ajouter au document.

Les samples montrant comment créer un document multipage avec cette technique sont disponibles ici

Ce document intitulé « [WPF] Génération d'un document XPS multipage » issu de CodeS SourceS (codes-sources.commentcamarche.net) est mis à disposition sous les termes de la licence Creative Commons. Vous pouvez copier, modifier des copies de cette page, dans les conditions fixées par la licence, tant que cette note apparaît clairement.
Rejoignez-nous