Cette page peut contenir du texte traduit automatiquement.

Taille, position et rendu des conteneurs

Le contenu est la partie la plus importante d’un document. Cela ne fait aucun doute. Un autre élément crucial est la mise en forme, qui crée une communication claire, professionnelle et efficace. Un document correctement mis en forme est visuellement attrayant, lisible et facile à parcourir.

Vous savez peut-être déjà comment organiser le contenu à l’aide de conteneurs. Et comment leur appliquer une couleur d’arrière-plan. Cet article décrit comment spécifier la taille et la position des conteneurs. Il couvre également des capacités avancées comme le rendu conditionnel du contenu. Il explique aussi la prise en charge des directions du contenu de droite à gauche.

Positionnement des conteneurs

La classe LayoutContainer fournit tout ce dont vous avez besoin pour disposer vos conteneurs de manière professionnelle. En appliquant des marges internes et l’alignement, vous pouvez créer un document qui laisse une impression positive à ses utilisateurs.

Cet article fait partie d’une série sur Layout API pour la génération de PDF. Si vous découvrez l’API, lisez d’abord la partie Premiers pas avec Layout API.

Taille

Par défaut, les conteneurs occupent la plus petite zone requise pour leur contenu. Autrement dit, la taille du conteneur est égale à la taille intrinsèque de son contenu.

La taille intrinsèque d’une image est déterminée par les dimensions du fichier image lui-même. La taille intrinsèque d’une plage de texte correspond à la taille de la zone qui couvre tous les glyphes de la plage.

La taille d’un conteneur composé comme Column ou Table dépend de la taille des éléments du conteneur.

Width & Height

Il est possible de spécifier une largeur et une hauteur exactes d’un conteneur à l’aide des méthodes Width et Height. C’est très pratique pour les conteneurs d’espace réservé.

Une taille exacte fonctionne aussi très bien pour les images. En effet, Layout API les met à l’échelle pour qu’elles s’adaptent au conteneur ou le remplissent, selon leur ImageContentMode.

Vous devez faire attention avec les tailles exactes pour les conteneurs composés et les conteneurs contenant du texte. Vous obtiendrez une LayoutException lorsqu’il n’est pas possible de faire tenir un contenu dans la taille fournie.

Il existe des cas où vous souhaitez seulement définir une contrainte sur la largeur ou la hauteur. Vous pouvez définir des contraintes à l’aide des méthodes MinWidth, MinHeight, MaxWidth et MaxHeight.

Veuillez noter que la bibliothèque lèvera une LayoutException lorsqu’il n’est pas possible de satisfaire les contraintes.

Extend

Un conteneur peut s’étendre pour occuper l’espace disponible maximal. C’est utile lorsque vous ne connaissez pas une taille exacte ni des contraintes de taille.

Utilisez la méthode ExtendHorizontal lorsque vous voulez que le conteneur occupe tout l’espace disponible uniquement dans la direction horizontale. La méthode ExtendVertical est utile lorsque vous voulez étendre le conteneur uniquement dans la direction verticale. La méthode Extend fait en sorte que le conteneur occupe tout l’espace disponible dans les deux directions.

var gray = new PdfGrayColor(75);
var text = "Content goes here";
var size = new PdfSize(150, 50);

PdfDocumentBuilder.Create().Generate("positioning-extend.pdf", doc =>
{
    for (int i = 0; i < 4; i++)
    {
        doc.Pages(page =>
        {
            page.Size(size);
            page.Content().Row(r =>
            {
                var container = r.AutoItem().Background(gray);
                switch (i)
                {
                    case 0:
                        container.Text(text);
                        break;

                    case 1:
                        container.ExtendHorizontal().Text(text);
                        break;

                    case 2:
                        container.ExtendVertical().Text(text);
                        break;

                    case 3:
                        container.Extend().Text(text);
                        break;
                }
            });
        });
    }
});

Le résultat du code ci-dessus se trouve dans positioning-extend.pdf. Comme vous pouvez le voir, chacune des quatre pages contient le même texte sur fond gris. Mais la taille du conteneur est différente sur chaque page.

MinimalBox

La classe LayoutContainer fournit la méthode MinimalBox. C’est en quelque sorte l’inverse des méthodes Extend. La méthode MinimalBox produit des conteneurs imbriqués qui n’utilisent que l’espace minimal nécessaire au contenu.

var gray = new PdfGrayColor(75);
var size = new PdfSize(150, 50);

PdfDocumentBuilder.Create().Generate("positioning-minimalbox.pdf", doc =>
{
    doc.Pages(page =>
    {
        page.Size(size);
        page.Content().MinimalBox().Background(gray).Text("I don't want more space");
    });

    doc.Pages(page =>
    {
        page.Size(size);
        page.Content().Background(gray).Text("I'll take everything");
    });
});

Le résultat du code ci-dessus se trouve dans positioning-minimalbox.pdf. À cause de l’appel à MinimalBox, le texte de la première page n’occupe que l’espace requis. Sur la deuxième page, le texte couvre toute la page.

Scale

Il est possible de mettre à l’échelle n’importe quel contenu dans un conteneur. La méthode Scale affecte le contenu dans les directions horizontale et verticale. Utilisez les méthodes ScaleHorizontal ou ScaleVertical pour modifier le contenu dans une seule direction. Les deux dernières méthodes ne conservent pas le rapport d’aspect du contenu.

Des valeurs de mise à l’échelle inférieures à 1 réduisent la zone occupée par un conteneur. Des valeurs supérieures à 1 augmentent cette zone. Pour inverser le contenu dans un conteneur, utilisez une valeur de mise à l’échelle négative. Par exemple, ScaleVertical(-1) produit une version retournée du contenu d’origine.

PdfDocumentBuilder.Create().Generate("positioning-scale.pdf", doc =>
{
    doc.Pages(page =>
    {
        page.Content()
            .MinimalBox()
            .Column(column =>
            {
                var scales = new[] { 0.5f, 0.75f, 1, 1.3f, 1.5f };

                foreach (var scale in scales)
                {
                    var percent = (int)(scale * 100);
                    column.Item()
                        .Scale(scale)
                        .Text(FormattableString.Invariant($"Scale equals {scale} ({percent}%)."))
                            .FontSize(20);

                    column.Item().LineHorizontal(0.5);
                }
            });
    });
});

Le résultat du code ci-dessus se trouve dans positioning-scale.pdf.

ScaleToFit

Vous pouvez réduire le contenu pour qu’il tienne dans l’espace disponible. Par exemple, lorsque vous avez une zone fixe pour afficher le nom ou l’adresse d’une personne. Bien sûr, vous pouvez agrandir la zone dans le cas d’un nom plus long. Mais une approche plus simple consiste peut-être à réduire légèrement le texte. Utilisez la méthode ScaleToFit pour réduire le contenu.

ScaleToFit conserve le rapport d’aspect du contenu. La méthode n’agrandit jamais le contenu. Veuillez noter que cette méthode effectue des calculs itératifs. Cela peut ralentir le processus de génération du PDF.

PdfDocumentBuilder.Create().Generate("positioning-scaletofit.pdf", doc =>
{
    doc.Pages(page =>
    {
        page.Content().Column(column =>
        {
            for (int i = 0; i < 5; i++)
            {
                column.Item()
                    .Width(230 - 20 * i)
                    .Height(20)
                    .ScaleToFit()
                    .Border(b => b.Thickness(0.5))
                    .Text(" This text should fit into the changing width.");
            }
        });
    });
});

Le résultat du code ci-dessus se trouve dans positioning-scaletofit.pdf.

AspectRatio

Le rapport d’aspect définit la relation proportionnelle entre la largeur et la hauteur d’un conteneur. Pour connaître le rapport d’aspect d’un conteneur, divisez sa largeur par sa hauteur.

Utilisez la méthode AspectRatio pour spécifier le rapport d’aspect d’un conteneur. Elle est utile lorsque vous concevez un conteneur réutilisable pour différentes mises en page ou différentes tailles de page.

PdfDocumentBuilder.Create().Generate("positioning-aspectratio.pdf", doc =>
{
    var ratios = new double[] { 0.25, 0.5, 1, 2 };
    foreach (var ratio in ratios)
    {
        var ratioText = ratio.ToString(CultureInfo.InvariantCulture);
        doc.Pages(page =>
        {
            page.Size(200, 200);
            page.Content().Column(column =>
            {
                column.Item()
                    .AspectRatio(ratio)
                    .Background(new PdfGrayColor(75))
                    .Text($"Width / Heigth = {ratioText}");
            });
        });
    }
});

Le résultat du code ci-dessus se trouve dans positioning-aspectratio.pdf.

La méthode possède un paramètre optionnel de type AspectRatioMode. Utilisez ce paramètre pour spécifier comment redimensionner le contenu tout en conservant le rapport d’aspect.

Un conteneur avec un rapport d’aspect spécifié occupe autant d’espace que possible. Selon le mode, le conteneur essaiera d’occuper toute la zone disponible (par défaut), la largeur ou la hauteur.

Veuillez noter que la bibliothèque peut lever une LayoutException. Cela se produit lorsqu’elle ne peut pas satisfaire les exigences de taille, de rapport d’aspect et de mode de rapport d’aspect.

Unconstrained

Les conteneurs peuvent ne comporter aucune contrainte de taille. Utilisez la méthode Unconstrained pour supprimer toutes les contraintes de taille d’un conteneur.

Le contenu d’un conteneur sans contrainte occupe un espace dont la taille est égale à la taille intrinsèque du contenu. Le conteneur sans contrainte lui-même n’occupe aucun espace. Par conséquent, des conteneurs frères peuvent recouvrir le contenu du conteneur sans contrainte.

PdfDocumentBuilder.Create().Generate("positioning-unconstrained.pdf", doc =>
{
    doc.Pages(page =>
    {
        page.Content().MinimalBox()
            .Border(b => b.Thickness(0.5))
            .Column(column =>
            {
                column.Item().Text("First item");

                column.Item().Unconstrained()
                    .Text("Second item ignores all size constraints");

                // en utilisant une ligne vide pour le troisième élément
                column.Item().Text(new string(' ', 20))
                    .BackgroundColor(new PdfRgbColor(187, 237, 237), 50);

                column.Item().Text("Fourth item");
            });
    });
});

Le résultat du code ci-dessus se trouve dans positioning-unconstrained.pdf. Dans le code, j’ai utilisé une ligne d’espaces avec un arrière-plan semi-transparent pour le troisième élément de la colonne. Comme vous pouvez le voir, le troisième élément recouvre partiellement le deuxième élément (sans contrainte).

Position

La position d’un conteneur dépend de plusieurs facteurs. Certains d’entre eux sont l’alignement, les marges internes, la position du conteneur parent et la direction du contenu. Par défaut, tout conteneur s’ancre à la position disponible la plus à gauche et la plus haute.

Padding

L’une des exigences les plus courantes consiste à ajouter de l’espace autour du contenu d’un conteneur. La classe LayoutContainer fournit un ensemble de méthodes pour définir la zone de marge interne d’un conteneur. La zone de marge interne correspond à l’espace entre son contenu et sa bordure. Autrement dit, la marge interne représente l’espace intérieur qui entoure le contenu.

La méthode Padding définit en une fois les marges internes sur les quatre côtés d’un conteneur. Utilisez la méthode PaddingHorizontal pour spécifier les marges internes uniquement à gauche et à droite. La méthode PaddingVertical fait de même uniquement en haut et en bas. Pour définir des marges internes individuellement sur un côté, utilisez l’une des méthodes PaddingTop/Bottom/Left/Right.

Align

Pour modifier la position d’un conteneur, utilisez les méthodes d’alignement. Les méthodes AlignLeft/AlignCenter/AlignRight appliquent un alignement horizontal et renvoient un conteneur imbriqué. Les méthodes AlignTop/AlignMiddle/AlignBottom renvoient un conteneur imbriqué avec un alignement vertical correspondant.

Un conteneur auquel un alignement est appliqué explicitement occupe la zone ayant la largeur et/ou la hauteur minimales requises. Le code suivant crée une colonne avec deux éléments. Un élément a un alignement appliqué explicitement.

PdfDocumentBuilder.Create().Generate("positioning-alignment.pdf", doc =>
{
    var color = new PdfRgbColor(187, 237, 237);
    var text = "Hello";
    doc.Pages(page =>
    {
        page.Size(200, 100);
        page.Content().Column(c =>
        {
            c.Item().Extend().Background(color).Text(text);
            c.Item().Extend().AlignLeft().Background(color).Text(text);
        });
    });
});

L’appel à Extend fait en sorte que les deux éléments occupent toute la page. J’appelle la méthode AlignLeft sur le deuxième élément. Cet appel ne modifie pas la position, car le conteneur de l’élément aligne le texte à gauche par défaut. Mais l’alignement appliqué explicitement modifie la zone occupée par le deuxième élément.

Le résultat du code ci-dessus se trouve dans positioning-alignment.pdf.

Translate

Pour repositionner un conteneur horizontalement et/ou verticalement, utilisez les méthodes Translate/TranslateX/TranslateY. La première déplace les conteneurs à la fois horizontalement et verticalement. Les deux autres déplacent les conteneurs dans une seule direction.

Toutes ces méthodes remplacent la position mais conservent les contraintes de taille. Le conteneur déplacé peut chevaucher d’autres conteneurs. Utilisez des valeurs de paramètre négatives pour déplacer vers la gauche et/ou vers le haut. Les valeurs positives provoquent un déplacement vers la droite et/ou vers le bas.

PdfDocumentBuilder.Create().Generate("positioning-translate.pdf", doc =>
{
    doc.Pages(page =>
    {
        page.Size(200, 100);
        page.Content().Row(r =>
        {
            r.ConstantItem(50)
                .Background(new PdfRgbColor(187, 237, 237))
                .Text("Left");

            r.ConstantItem(50)
                // déplacer cet élément de 10 points vers la gauche et de 5 points vers le bas
                .Translate(-10, 5)
                .Background(new PdfRgbColor(15, 130, 9))
                .Text("Right");
        });
    });
});

Le résultat du code ci-dessus se trouve dans positioning-translate.pdf.

Rotate

Le contenu tourné, en particulier le texte, peut améliorer vos documents de différentes façons. Par exemple, vous pouvez économiser de l’espace et rendre votre document plus attrayant et plus agréable visuellement.

La classe LayoutContainer propose deux approches pour faire pivoter le contenu. Quelle que soit l’approche utilisée, le conteneur avec le contenu pivoté respecte les contraintes de position et de taille.

Rotation de 90 degrés

Les méthodes RotateRight et RotateLeft font pivoter le contenu de 90 degrés dans le sens horaire et antihoraire, respectivement.

Le code suivant montre comment créer un document avec du texte vertical à côté du contenu principal de la page.

PdfDocumentBuilder.Create().Generate("positioning-rotate.pdf", doc =>
{
    var lightGray = new PdfGrayColor(90);
    doc.Pages(page =>
    {
        page.Size(298, 210);
        page.Content().Row(r =>
        {
            r.AutoItem()
                .RotateLeft()
                .Background(lightGray)
                .Text("This content goes up");

            r.RelativeItem(1)
                .ExtendVertical()
                .PaddingHorizontal(10)
                .Column(t =>
                {
                    for (int i = 0; i < 15; i++)
                        t.Item().Text("The main content line goes here");
                });

            r.AutoItem()
                .RotateRight()
                .Background(lightGray)
                .Text("This content goes down");
        });
    });
});

Le résultat du code ci-dessus se trouve dans positioning-rotate.pdf.

Rotation à n’importe quel angle

La méthode Rotate fait pivoter le contenu d’un nombre arbitraire de degrés. Les nombres positifs entraînent une rotation horaire. Les nombres négatifs sont utilisés pour une rotation antihoraire.

Le point d’origine de la rotation est le coin supérieur gauche du conteneur. Le contenu pivoté peut chevaucher d’autres conteneurs.

PdfDocumentBuilder.Create().Generate("positioning-rotate2.pdf", doc =>
{
    doc.Pages(page =>
    {
        page.Size(298, 210);
        page.Content()
            .Padding(25)
            .Background(new PdfGrayColor(70)) // gris
            .AlignCenter()
            .AlignMiddle()

            .Background(new PdfGrayColor(100)) // blanc

            .Rotate(30)

            .Width(100)
            .Height(100)
            .Background(new PdfRgbColor(187, 237, 237)); // bleu
    });
});

Le résultat du code ci-dessus se trouve dans positioning-rotate2.pdf.

Pour modifier le point d’origine de la rotation, appelez l’une des méthodes Translate avant l’appel Rotate. N’oubliez pas de ramener l’origine à sa position initiale après l’appel.

// déplacer le point d’origine de la rotation
.TranslateX(50)
.TranslateY(50)

.Rotate(30)

// revenir en arrière
.TranslateX(-50)
.TranslateY(-50)

Mise en page conditionnelle

La mise en page de votre document PDF peut dépendre d’une condition. Par exemple, vous pouvez utiliser un alignement ou une couleur d’arrière-plan différents pour les lignes paires et impaires d’une colonne.

Utilisez la méthode Container pour insérer un conteneur imbriqué dont la mise en page dépend d’une condition. L’appel à cette méthode ne rompt pas la chaîne d’appels.

PdfDocumentBuilder.Create().Generate("positioning-container.pdf", doc =>
{
    doc.Pages(page =>
    {
        page.Content().Column(c =>
        {
            for (int i = 0; i < 15; i++)
            {
                c.Item()
                    .TextStyle(TextStyle.Parent.FontSize(14))
                    .Container(x => i % 2 == 0 ? x.Background(new PdfGrayColor(70)) : x)
                    .Text($"Row {i + 1}");
            }
        });
    });
});

Le résultat du code ci-dessus se trouve dans positioning-container.pdf.

DSL

Certaines parties d’un document peuvent utiliser la même mise en page. Par exemple, elles peuvent définir une bordure visuellement identique ou utiliser le même formatage. Selon le principe « ne vous répétez pas », je recommande d’extraire le code commun dans une méthode.

L’utilisation d’une méthode d’extension pour le code commun offre deux avantages :

  • Vous pouvez utiliser la méthode dans des chaînes d’appels de méthodes
  • Vous pouvez donner un nom significatif à un ensemble d’appels de méthodes

Avec ces avantages, vous pouvez construire un langage spécifique au domaine (DSL). Avec le DSL, votre code de mise en page peut être plus court et plus facile à comprendre.

static class LayoutHelpers
{
    public static LayoutContainer NumberCell(this Table table)
        => table.Cell().Border(b => b.Thickness(0.5)).PaddingHorizontal(10);
}

PdfDocumentBuilder.Create().Generate("positioning-dsl.pdf", doc => doc.Pages(page =>
{
    page.Content().Table(t =>
    {
        t.Columns(c =>
        {
            for (int i = 0; i < 4; ++i)
                c.ConstantColumn(50);
        });

        for (int i = 0; i < 16; i++)
            t.NumberCell().Text($"{i + 1}");
    });
}));

Processus de rendu

Le module complémentaire Layout organise tout contenu que vous placez dans un conteneur selon les contraintes de taille et de position. Certains contenus peuvent s’étendre sur plusieurs pages. Le contenu est rendu dans un ordre strict. Le flux de contenu est un autre nom pour cet ordre.

La classe LayoutContainer fournit plusieurs méthodes permettant d’ajuster le flux de contenu. Vous n’en aurez pas forcément besoin à chaque fois, mais il existe des cas où il n’y a pas d’autre moyen d’obtenir la mise en page requise.

PageBreak

Lorsque vous devez commencer un bloc de contenu sur une nouvelle page, utilisez la méthode PageBreak. Par exemple, vous pouvez utiliser cette méthode pour commencer un élément Column sur une nouvelle page.

Voici un exemple de code qui divise une colonne de sorte que chaque page ne contienne que deux lignes.

PdfDocumentBuilder.Create().Generate("positioning-pagebreak.pdf", doc => doc.Pages(page =>
{
    page.Size(200, 100);
    page.Content().Column(c =>
    {
        for (int i = 1; i <= 10; ++i)
        {
            c.Item().Text($"Item {i}");

            if (i % 2 == 0)
                c.Item().PageBreak();
        }
    });
}));

Le résultat du code ci-dessus se trouve dans positioning-pagebreak.pdf.

ShowIf

Selon une condition, vous pouvez avoir besoin d’afficher ou de masquer un conteneur. La méthode ShowIf est essentiellement un sucre syntaxique pour ce cas particulier de mise en page conditionnelle.

Dans le code suivant, j’utilise la méthode ShowIf pour insérer une ligne verticale après chaque 5 éléments d’une ligne.

PdfDocumentBuilder.Create().Generate("positioning-showif.pdf", doc => doc.Pages(page =>
{
    page.Size(200, 100);
    page.Content().Row(r =>
    {
        for (int i = 0; i < 10; ++i)
        {
            r.AutoItem().Text(i.ToString());
            r.AutoItem().ShowIf(i > 0 && (i + 1) % 5 == 0).LineVertical(0.5);
        }
    });
}));

Le résultat du code ci-dessus se trouve dans positioning-showif.pdf.

ShowOnce

Vous pouvez empêcher qu’un fragment de contenu se répète sur les pages suivantes. Utilisez la méthode ShowOnce pour indiquer au moteur de mise en page de rendre le contenu complètement une seule fois.

Examinez le code suivant pour voir comment l’appel à ShowOnce empêche « Environment » d’apparaître sur la deuxième page.

PdfDocumentBuilder.Create().Generate("positioning-showonce.pdf", doc => doc.Pages(page =>
{
    page.Size(200, 100);
    page.Content().Row(r =>
    {
        r.RelativeItem()
            .Background(new PdfGrayColor(75))
            .Border(b => b.Thickness(0.5))
            .Padding(5)
            .ShowOnce()
            .Text("Environment");

        r.RelativeItem()
            .Border(b => b.Thickness(0.5))
            .Padding(5)
            .Column(c =>
            {
                c.Item().Text(Environment.OSVersion.VersionString);
                c.Item().Text(string.Empty);
                c.Item().Text(
                    Environment.GetEnvironmentVariable("PROCESSOR_IDENTIFIER")
                    ?? string.Empty
                );
            });
    });
}));

Le résultat du code ci-dessus se trouve dans positioning-showonce.pdf.

ShowEntire

Le comportement par défaut consiste à répartir le contenu entre les pages lorsqu’il ne tient pas sur une seule page. Utilisez la méthode ShowEntire pour rendre le conteneur entier sur une seule page.

Veuillez noter que la bibliothèque lève une LayoutException lorsqu’il n’est pas possible de faire tenir tout le contenu sur une seule page.

En raison de l’appel à ShowEntire dans le code suivant, le texte du deuxième élément commence sur la deuxième page. Sans cet appel, il commencerait sur la première page, juste après le texte du premier élément.

PdfDocumentBuilder.Create().Generate("positioning-showentire.pdf", doc => doc.Pages(page =>
{
    page.Size(100, 100);
    page.Content().Column(c =>
    {
        c.Item().Text(t =>
        {
            for (var i = 0; i < 4; i++)
                t.Line($"First item line {i + 1}");
        });

        c.Item()
            .Background(new PdfRgbColor(250, 123, 5))
            .ShowEntire()
            .Text(t =>
            {
                for (var i = 0; i < 4; i++)
                    t.Line($"Second item line {i + 1}");
            });
    });
}));

Le résultat du code ci-dessus se trouve dans positioning-showentire.pdf.

EnsureSpace

Dans un certain sens, EnsureSpace est un cas particulier de la méthode ShowEntire. La différence est que EnsureSpace n’exige pas que tout le contenu tienne sur une page. La méthode essaie seulement de faire tenir une partie du contenu avec la hauteur spécifiée. Tout le reste ira sur la page suivante.

Si une zone non occupée de la page courante a une hauteur inférieure à celle demandée, l’ensemble du contenu sera rendu sur une nouvelle page. Ici, la méthode produira le même résultat que la méthode ShowEntire.

StopPaging

Utilisez la méthode StopPaging pour produire une sortie sur au plus une page. L’appel de cette méthode sur un conteneur empêche sa pagination. Le module complémentaire Layout ne divisera pas le contenu de ce conteneur entre les pages. Il ne rendra aucune donnée qui ne tient pas sur une page.

L’exemple de code suivant ajoute deux ensembles de pages au document. Les deux ensembles utilisent une liste de noms de jours de la semaine comme contenu. Le premier ensemble ne comporte qu’une seule page, car le code appelle la méthode StopPaging pour le conteneur de contenu des pages.

PdfDocumentBuilder.Create().Generate("positioning-stoppaging.pdf", doc =>
{
    static Action<TextContainer> produceText(string heading)
    {
        var text = string.Join('\n', DateTimeFormatInfo.InvariantInfo.DayNames);
        return t =>
        {
            t.Line(heading).BackgroundColor(new PdfRgbColor(250, 123, 5));
            t.Span(text);
        };
    }

    doc.Pages(page =>
    {
        page.Size(100, 100);
        page.Content()
            .StopPaging()
            .Text(produceText("Without paging:"));
    });

    doc.Pages(page =>
    {
        page.Size(100, 100);
        page.Content()
            .Text(produceText("Default behaviour:"));
    });
});

Le résultat du code ci-dessus se trouve dans positioning-stoppaging.pdf.

SkipOnce

Vous pouvez retarder l’apparition du contenu. Si un conteneur apparaît sur plus d’une page, utilisez SkipOnce pour ignorer la première page et rendre le contenu sur toutes les pages à partir de la deuxième.

Cette possibilité est utile pour toutes sortes d’en-têtes, mais vous pouvez aussi l’utiliser avec d’autres contenus. Vérifiez le code suivant pour voir comment l’appel à SkipOnce empêche l’en-tête d’apparaître sur la première page.

PdfDocumentBuilder.Create().Generate("positioning-skiponce.pdf", doc => doc.Pages(page =>
{
    page.Size(298, 210);

    page.Header()
        .SkipOnce()
        .Text("This header will appear starting from page 2")
        .Style(TextStyle.Parent.Underline());

    page.Content().Column(c =>
    {
        for (int i = 0; i < 5; i++)
        {
            if (i > 0)
                c.Item().PageBreak();

            c.Item().Text($"Page {i + 1}");
        }
    });
}));

Le résultat du code ci-dessus se trouve dans positioning-skiponce.pdf.

Direction du contenu

La direction du contenu par défaut est de gauche à droite. Les conteneurs alignent leur texte et les autres contenus à gauche.

Mais certaines langues s’écrivent de droite à gauche (par exemple l’arabe et l’hébreu). Lorsque vous créez du contenu dans ces langues, utilisez la méthode ContentFromRightToLeft. Son appel basculera la direction du contenu du conteneur vers la droite à gauche. La méthode changera aussi l’alignement par défaut.

Si la majeure partie du contenu de vos pages est dans une langue RTL, vous pouvez définir la direction de contenu de droite à gauche comme direction par défaut pour les pages. Utilisez pour cela la méthode PageLayout.ContentFromRightToLeft. Ensuite, pour remplacer la direction du contenu par défaut pour certains conteneurs, utilisez la méthode ContentFromLeftToRight.

Veuillez noter que la direction du contenu n’affecte pas l’alignement spécifié explicitement. Par exemple, un contenu aligné à droite restera à droite quelle que soit la direction du contenu définie pour son conteneur. L’ordre visuel des éléments enfants sera différent selon la direction du contenu.