Cette page peut contenir du texte traduit automatiquement.

Conteneurs composés

Les conteneurs complexes jouent un rôle crucial dans la structuration et l'organisation du contenu. En utilisant un conteneur approprié, vous pouvez facilement présenter du texte et des images de manière conviviale.

Il est tout à fait possible de construire un document en utilisant uniquement de simples conteneurs de texte et d'images. Cependant, certaines exigences sont difficiles, voire impossibles, à mettre en œuvre uniquement avec de simples conteneurs. Les conteneurs composés sont utiles dans de tels cas. De plus, les conteneurs complexes vous aident à atteindre vos objectifs avec moins de code.

Conteneurs composés

Utilisez les méthodes de la classe LayoutContainer pour ajouter des conteneurs complexes comme la Row et la Column aux pages du document. En utilisant ces conteneurs, vous pouvez implémenter d'autres conteneurs comme une grille et des listes. Il existe également les méthodes Inlined et Layers pour des cas moins courants mais néanmoins importants.

Cet article fait partie d'une série sur l'API Layout pour la génération de PDF. Si vous débutez avec l'API, lisez d'abord la partie Mise en route avec l'API Layout.

Bibliothèque Docotic.Pdf 9.5.17615-dev Module complémentaire de mise en page 9.5.17615-dev
Tests de régression 14,813 réussis Téléchargements totaux de NuGet 4,924,084

Row

Les conteneurs Row offrent de la place pour les articles disposés horizontalement sur une seule ligne. Chaque élément d'une rangée est un conteneur. Cela signifie que vous pouvez placer du contenu de différents types sur une seule ligne. Vous pouvez spécifier l'espacement entre les éléments en utilisant la méthode Spacing.

Tous les éléments d'une rangée ont la même hauteur. La bibliothèque utilise la hauteur de l'élément le plus haut comme hauteur de la ligne. Il existe trois façons de spécifier la largeur d'un élément. Vous devez en choisir un lors de la création de l'élément. Une ligne peut contenir des éléments créés de différentes manières.

La méthode Row.AutoItem crée un élément sans largeur explicitement spécifiée. Pour de tels éléments, la bibliothèque calcule la taille intrinsèque de leur contenu. La largeur du contenu calculée est la largeur de l'élément. Veuillez noter que les éléments créés avec AutoItem ne retournent pas à la ligne les longues lignes.

Utilisez la méthode ConstantItem pour créer un élément avec une largeur égale à un nombre exact de points.

Le RelativeItem est pratique lorsque vous ne connaissez pas les largeurs exactes des éléments de la ligne et que vous ne souhaitez pas utiliser de tailles intrinsèques. Au lieu de cela, vous pouvez spécifier des largeurs relatives pour les éléments de la ligne. La méthode accepte le nombre de parties que l’élément doit occuper. Le nombre total de parties est la somme de tous les nombres de tous les appels RelativeItem dans cette ligne.

Par exemple, s'il y a un appel RelativeItem, alors le numéro n'est pas important. L'article occupera toute la largeur disponible. Pour deux éléments ou plus, les nombres définissent la proportion.

row.RelativeItem(2)
row.RelativeItem(3)
row.RelativeItem(1)

Tous les éléments créés avec le code ci-dessus comportent 6 parties (2 + 3 + 1 = 6). Les éléments individuels occupent respectivement 2 parties sur 6, 3 parties sur 6 et 1 partie sur 6.

L'API Layout utilise la formule suivante pour calculer la largeur d'une pièce :

PartWidth = (RowWidth - AutoWidth - ConstantWidth) / TotalParts

où:
RowWidth = largeur du conteneur de lignes
AutoWidth = largeur de tous les éléments créés avec la méthode AutoItem
ConstantWidth = largeur de tous les éléments créés avec la méthode ConstantItem

Voici un exemple qui crée une ligne avec des éléments des trois types.

var monthNames = DateTimeFormatInfo.InvariantInfo.MonthNames;
var groups = new[]
{
    string.Join(", ", monthNames.Take(4)),
    string.Join(", ", monthNames.Skip(4).Take(4)),
    string.Join(", ", monthNames.Skip(8).Take(4)),
};

PdfDocumentBuilder.Create().Generate("compounds-row.pdf", doc => doc.Pages(page =>
{
    page.Content()
        .Padding(20)
        .MinimalBox()
        .Row(row =>
        {
            row.ConstantItem(100)
                .Background(new PdfRgbColor(187, 237, 237))
                .Text("100 points wide");

            for (int i = 0; i < groups.Length; i++)
            {
                row.AutoItem().LineVertical(0.1);

                var numberOfParts = groups.Length - i + 1;
                row.RelativeItem(numberOfParts)
                    .PaddingHorizontal(5)
                    .Text(t =>
                    {
                        t.Line($"{numberOfParts} parts wide");
                        t.Line();
                        t.Line(groups[i]);
                    });
            }
        });
}));

Vous pouvez voir le résultat du code dans compounds-row.pdf.

Column

Pour disposer les éléments verticalement, les uns après les autres, utilisez un conteneur Column. Chaque élément d'une colonne est un conteneur. Pour cette raison, vous pouvez placer du contenu de différents types dans une seule colonne.

La largeur de chaque élément est égale à la largeur de la colonne. La hauteur de chaque élément dépend de son contenu et de ses propriétés. Les conteneurs Column prennent en charge la pagination, de sorte que le module complémentaire Layout peut afficher les éléments d'une colonne sur plusieurs pages.

Par défaut, un conteneur Column n'a pas de contenu d'en-tête ou de pied de page. Utilisez les méthodes Header et Footer pour accéder et configurer les conteneurs correspondants. Lorsque les éléments de colonne occupent plusieurs pages, la bibliothèque répète les en-têtes et les pieds de page sur chaque page.

Utilisez la méthode Spacing pour ajouter un espace vertical entre les éléments de colonne. Veuillez noter que la bibliothèque n'applique pas d'espacement entre l'en-tête et le premier élément. La bibliothèque n'ajoute pas non plus d'espace avant le pied de page.

PdfDocumentBuilder.Create().Generate("compounds-column.pdf", doc => doc.Pages(page =>
{
    page.Size(PdfPaperSize.A6);

    page.Content()
        .Padding(20)
        .Column(column =>
        {
            column.Header()
                .Background(new PdfRgbColor(187, 237, 237))
                .Padding(5)
                .Text("Month names");

            for (int i = 0; i < 12; i++)
            {
                column.Item().Background(
                    new PdfGrayColor(i % 2 == 0 ? 90 : 100))
                    .Padding(5)
                    .Text(DateTimeFormatInfo.InvariantInfo.MonthNames[i]);
            }

            column.Footer().LineHorizontal(1);
        });
}));

Vous pouvez voir le résultat du code dans compounds-column.pdf.

Grille

Les dispositions en grille organisent les éléments en colonnes et en lignes. Les grilles sont similaires aux tableaux à cet égard. L'API Layout ne fournit pas de type de conteneur spécial pour les grilles. Vous pouvez implémenter une disposition en grille en utilisant les conteneurs Column et Row.

Il est utile de considérer une grille comme une colonne, chacun de ses éléments étant une ligne. Les conteneurs Column et Row offrent la possibilité de définir l'espacement entre les éléments. Vous pouvez avoir un en-tête et un pied de page, si vous le souhaitez.

Chaque ligne peut avoir une disposition indépendante. Il peut y avoir un nombre différent d'éléments dans chaque ligne. Les articles peuvent avoir différentes largeurs et hauteurs. Il est possible d'ajouter un espace supplémentaire avant, après ou entre les éléments d'une rangée. Utilisez pour cela des objets sans contenu ni décoration.

var blue = new PdfRgbColor(187, 237, 237);
var darkerBlue = blue.Darken(50);
PdfDocumentBuilder.Create().Generate("compounds-grid.pdf", doc => doc.Pages(page =>
{
    page.Size(300, 200);

    page.Content().Padding(15).Column(column =>
    {
        column.Spacing(10);

        column.Item().Row(row =>
        {
            row.Spacing(10);

            row.ConstantItem(100).Background(darkerBlue).Height(40);
            row.RelativeItem(4).Background(blue);
        });

        column.Item().Row(row =>
        {
            row.Spacing(10);

            row.RelativeItem(2).Background(blue).Height(60);
            row.RelativeItem(1);
            row.RelativeItem(2).Background(blue);
        });

        column.Item().Row(row =>
        {
            row.Spacing(10);

            row.RelativeItem(1).Background(blue).Height(50);
            row.RelativeItem(3).Background(blue);
            row.ConstantItem(50).Background(darkerBlue);
        });
    });
}));

Vous pouvez voir le résultat du code dans compounds-grid.pdf.

Listes

Les listes améliorent la lisibilité en décomposant les informations en points concis. Les éléments de la liste peuvent comporter des chiffres, des puces et d’autres symboles à côté du texte qu’ils contiennent. Vous pouvez facilement implémenter une disposition de liste en utilisant les conteneurs Column et Row. L'API Layout ne fournit pas de type de conteneur spécial pour les listes.

Consultez l'exemple de code qui crée une liste de mois par saisons. Veuillez noter que la liste a un en-tête. Si les éléments contiennent du texte qui peut passer à la ligne suivante, utilisez la méthode RelativeItem ou ConstantItem pour la partie texte de l'élément.

var monthNames = DateTimeFormatInfo.InvariantInfo.MonthNames.ToList();
monthNames.Insert(0, monthNames[11]);

PdfDocumentBuilder.Create().Generate("compounds-list.pdf", doc => doc.Pages(page =>
{
    page.Size(150, 200);

    page.Content().Padding(5).Column(column =>
    {
        column.Header()
            .Text("Months by seasons:")
            .Style(TextStyle.Parent.Underline());

        for (int i = 0; i < 4; i++)
        {
            var season = string.Join(", ", monthNames.Skip(i * 3).Take(3));
            column.Item().Row(row =>
            {
                row.Spacing(2);

                row.AutoItem().Text("•");
                row.RelativeItem().Text(season);
            });
        }
    });
}));

Vous pouvez voir le résultat du code dans compounds-list.pdf.

Table

Les dispositions de tableau organisent les éléments en colonnes et en lignes. Le type de conteneur Table offre un ensemble complet de fonctionnalités et peut vous aider dans les cas les plus sophistiqués. Découvrez toutes les fonctionnalités dans l'article Conteneur Table.

InlineContainer

Vous pouvez remplir un conteneur avec une collection d'autres conteneurs. Commencez par appeler la méthode LayoutContainer.Inlined. Appelez ensuite la méthode Item du InlineContainer fourni pour ajouter des conteneurs enfants.

Le module complémentaire Layout place les conteneurs les uns après les autres. S'il n'y a pas d'espace pour placer un élément, la bibliothèque commence une nouvelle ligne. Utilisez les méthodes Spacing/HorizontalSpacing/VerticalSpacing pour ajouter de l'espace entre les éléments.

Vous pouvez affecter la position des éléments dans le conteneur à l'aide de méthodes d'alignement. Les méthodes AlignTop/AlignMiddle/AlignBottom alignent les éléments verticalement. Pour la direction horizontale, utilisez les méthodes AlignLeft/AlignCenter/AlignRight/AlignJustify.

Il y a un cas particulier. La méthode AlignSpaceAround qui aligne les éléments horizontalement. Il ajoute également un espacement supplémentaire avant le premier élément et après le dernier élément.

var orange = new PdfRgbColor(250, 123, 5);
var brown = orange.Darken(50);
var itemProps = new (int Width, PdfColor Color)[] {
    (20, orange), (30, orange), (50, brown), (50, orange), (50, orange),
    (30, orange), (20, brown), (30, orange), (50, brown), (10, brown)
};

PdfDocumentBuilder.Create().Generate("compounds-inlined.pdf", doc => doc.Pages(page =>
{
    page.Size(150, 120);

    page.Content().Inlined(c =>
    {
        c.Spacing(5);

        foreach (var (Width, Color) in itemProps)
            c.Item().Height(30).Width(Width).Background(Color);
    });
}));

Vous pouvez voir le résultat du code dans compounds-inlined.pdf.

LayerContainer

Vous devrez peut-être placer du contenu en dessous et/ou au-dessus du contenu de la page principale. Le cas d’utilisation évident consiste à ajouter un filigrane au-dessus des pages PDF.

Tout d'abord, récupérez un objet LayerContainer en appelant la méthode LayoutContainer.Layers. Compte tenu de l'objet, vous pouvez commencer à ajouter des calques. L'appel de la méthode Layer ajoute une couche secondaire. Appelez la méthode PrimaryLayer pour ajouter la couche de contenu principale. Vous devez ajouter exactement une couche principale.

L'API Layout composera les calques dans le même ordre que vous les créez. Les calques ajoutés avant le calque principal passeront en arrière-plan. Tous les calques ajoutés après le calque principal passeront au-dessus du contenu principal. Le conteneur répète les couches secondaires sur toutes les pages occupées par le contenu principal.

Voici un exemple de code expliquant comment ajouter des filigranes aux pages PDF.

PdfDocumentBuilder.Create().Generate("compounds-layers.pdf", doc => doc.Pages(page =>
{
    var largeRedText = TextStyle.Parent.FontSize(48)
        .FontColor(new PdfRgbColor(235, 64, 52));

    page.Size(400, 250);

    page.Content()
        .Padding(25)
        .Layers(layers =>
        {
            layers.Layer()
                .AlignCenter()
                .Text(text => text.CurrentPageNumber().Style(largeRedText));

            layers.PrimaryLayer()
                .Background(new PdfGrayColor(85), 65)
                .Padding(25)
                .Text(new string('_', 790));

            layers.Layer()
                .AlignCenter()
                .AlignMiddle()
                .Text("Watermark")
                .Style(largeRedText);
        });
}));

Vous pouvez voir le résultat du code dans compounds-layers.pdf.

Filigranes

L'une des exigences courantes consiste à ajouter un filigrane au PDF. Cette exigence peut exister pour diverses raisons. Vous pouvez ajouter un filigrane au PDF pour identifier la propriété ou pour souligner la confidentialité ou la sensibilité des informations contenues dans le PDF.

Une approche pour filigraner des PDF consiste à utiliser des calques. Voir l'exemple dans la section précédente. Laissez-moi vous montrer une autre approche.

J'utiliserai des conteneurs d'arrière-plan et de premier plan de page pour filigraner les PDF. Le module complémentaire Layout répète ces conteneurs sur les pages suivantes. Chaque page contenant du contenu de document principal contiendra également des conteneurs d'arrière-plan et de premier plan. Cela les rend adaptés à la tâche.

Je commence par ajouter une image au conteneur d'arrière-plan. Vous pouvez ajouter votre logo au PDF de la même manière. L'image apparaîtra derrière le contenu de la page. Le nombre de pages de votre document utilisant l'image d'arrière-plan n'a pas d'importance. L'API ajoutera une seule copie des octets de l'image au PDF généré.

Le contenu du document principal peut être n'importe quoi. Pour cet exemple de code, j'utilise le célèbre texte Lorem Ipsum.

Le filigrane de texte va dans le conteneur de premier plan. Le texte lui-même peut être n'importe quoi et vous pouvez utiliser n'importe quelle couleur ou police. J'ai utilisé du texte pivoté dessiné avec des lettres rouges semi-transparentes de plus grande taille.

L'exemple de code télécharge de manière asynchrone à la fois l'image et le texte à partir de notre référentiel d'exemples de code. Bien entendu, vous pouvez utiliser une image locale et/ou lire le texte d’un fichier.

var urlPrefix =
    "https://raw.githubusercontent.com/BitMiracle/Docotic.Pdf.Samples/master/Samples/Sample%20Data/";

using var client = new HttpClient();
using var imageResponse = await client.GetAsync(urlPrefix + "watermark-background.png");
using var imageStream = await imageResponse.Content.ReadAsStreamAsync().ConfigureAwait(false);

var loremIpsum = string.Empty;
using (var textResponse = await client.GetAsync(urlPrefix + "lorem-ipsum.txt"))
     loremIpsum = await textResponse.Content.ReadAsStringAsync().ConfigureAwait(false);

PdfDocumentBuilder.Create().Generate("compounds-watermarks.pdf", doc =>
{
    var image = doc.Image(imageStream);

    doc.Pages(page =>
    {
        page.Size(400, 250);

        page.Background()
            .AlignMiddle()
            .Image(image);

        page.Content()
            .Padding(25)
            .Text(loremIpsum);

        var largeRedText = TextStyle.Parent.FontSize(48)
            .FontColor(new PdfRgbColor(235, 64, 52), 50);
        page.Foreground()
            .Rotate(-30)
            .Translate(-50, 180)
            .Text("DO NOT COPY")
            .Style(largeRedText);
    });
});

Vous pouvez voir le résultat du code dans compounds-watermarks.pdf.

Exemple de code

Nous avons quelques exemples d'applications qui couvrent plus en détail les fonctionnalités susmentionnées. Veuillez prendre le temps de les vérifier.