Cette page peut contenir du texte traduit automatiquement.
Conteneurs composites
Les conteneurs composites 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 des conteneurs de texte et d’image simples. Cependant, certaines exigences sont difficiles, voire impossibles, à mettre en œuvre avec de simples conteneurs seuls. Les conteneurs composites aident dans ce type de cas. De plus, les conteneurs complexes vous aident à atteindre vos objectifs avec moins de code.

Utilisez les méthodes de la classe LayoutContainer pour ajouter aux pages du document des conteneurs complexes comme Row et Column. À l’aide de ces conteneurs, vous pouvez implémenter d’autres conteneurs comme les grilles et les 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 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.
Row
Les conteneurs Row offrent de l’espace pour des éléments disposés horizontalement sur une seule ligne. Chaque élément d’une ligne est un conteneur. Cela signifie que vous pouvez placer du contenu de types différents dans une seule ligne. Vous pouvez spécifier l’espacement entre les éléments à l’aide de la méthode Spacing.
Tous les éléments d’une ligne 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 une 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 calculée du contenu est la largeur de l’élément. Notez que les éléments créés avec AutoItem ne renvoient pas les longues lignes à la ligne.
Utilisez la méthode ConstantItem pour créer un élément dont la largeur est égale à un nombre exact de points.
RelativeItem est pratique lorsque vous ne connaissez pas la largeur exacte des éléments de la ligne et que vous ne souhaitez pas utiliser les tailles intrinsèques. À la place, vous pouvez spécifier des largeurs relatives pour les éléments de la ligne. La méthode accepte le nombre de parts que l’élément doit occuper. Le nombre total de parts est la somme de tous les nombres passés à tous les appels RelativeItem dans cette ligne.
Par exemple, s’il n’y a qu’un seul appel RelativeItem, le nombre n’a pas d’importance. L’élément 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 prennent 6 parts (2 + 3 + 1 = 6). Les éléments individuels occupent respectivement 2 parts sur 6, 3 parts sur 6 et 1 part sur 6.
Layout API utilise la formule suivante pour calculer la largeur d’une part :
PartWidth = (RowWidth - AutoWidth - ConstantWidth) / TotalParts
où :
RowWidth = largeur du conteneur de ligne
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. De ce fait, vous pouvez placer du contenu de types différents dans une seule colonne.
La largeur de chaque élément est égale à celle de la colonne. La hauteur de chaque élément dépend du contenu et des propriétés de l’élément. Les conteneurs Column prennent en charge la pagination, donc l’extension Layout peut afficher les éléments d’une colonne sur plus d’une page.
Par défaut, un conteneur Column ne contient pas de contenu d’en-tête ou de pied de page. Utilisez les méthodes Header et Footer pour accéder aux conteneurs correspondants et les configurer. Lorsque les éléments de la colonne occupent plus d’une page, la bibliothèque répète à la fois 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 la colonne. Notez 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 mises en page en grille organisent les éléments en colonnes et en lignes. À cet égard, les grilles sont similaires aux tableaux. Layout API ne fournit pas de type de conteneur spécifique pour les grilles. Vous pouvez implémenter une mise en page en grille à l’aide des 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 permettent tous deux 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. Le nombre d’éléments peut être différent dans chaque ligne. Les éléments peuvent avoir des largeurs et des hauteurs différentes. Il est possible d’ajouter un espace supplémentaire avant, après ou entre les éléments d’une ligne. Utilisez pour cela des éléments 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 liste peuvent contenir des numéros, des puces et d’autres symboles à côté du texte. Vous pouvez facilement implémenter une mise en page en liste à l’aide des conteneurs Column et Row. Layout API ne fournit pas de type de conteneur spécifique pour les listes.
Consultez l’exemple de code qui crée une liste de mois par saison. Notez que la liste comporte un en-tête. Si les éléments contiennent du texte susceptible de 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 mises en page en tableau organisent les éléments en colonnes et en lignes. Le type de conteneur Table offre un ensemble étendu de fonctionnalités et peut vous aider dans les cas les plus sophistiqués. Lisez la description de toutes les fonctionnalités dans l’article Conteneur de tableau.
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.
L’extension Layout place les conteneurs les uns après les autres sur une ligne. 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 modifier la position des éléments dans le conteneur à l’aide des 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 existe un cas particulier : la méthode AlignSpaceAround aligne les éléments horizontalement. Elle 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 pouvez avoir besoin de placer du contenu sous et/ou au-dessus du contenu principal de la page. Le cas d’usage évident est d’ajouter un filigrane sur les pages PDF.
Commencez par obtenir un objet LayerContainer en appelant la méthode LayoutContainer.Layers. Une fois l’objet obtenu, vous pouvez commencer à ajouter des calques. L’appel de la méthode Layer ajoute un calque secondaire. Appelez la méthode PrimaryLayer pour ajouter le calque du contenu principal. Vous devez ajouter exactement un calque principal.
Layout API composera les calques dans le même ordre que celui dans lequel vous les créez. Les calques ajoutés avant le calque principal iront en arrière-plan. Tous les calques ajoutés après le calque principal seront placés au-dessus du contenu principal. Le conteneur répète les calques secondaires sur toutes les pages occupées par le contenu principal.
Voici un exemple de code montrant 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 signaler la confidentialité ou la sensibilité des informations contenues dans le PDF.
Une approche du filigrane des PDF consiste à utiliser des calques. Voir l’exemple dans la section précédente. Laissez-moi vous montrer une autre approche.
Je vais utiliser les conteneurs d’arrière-plan et de premier plan de la page pour filigraner les PDF. L’extension Layout répète ces conteneurs sur les pages suivantes. Chaque page contenant le contenu principal du document contiendra également les conteneurs d’arrière-plan et de premier plan. Ils conviennent donc à cette 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. Peu importe le nombre de pages de votre document qui utilisent l’image d’arrière-plan. L’API n’ajoutera qu’une seule copie des octets de l’image au PDF généré.
Le contenu principal du document peut être n’importe quoi. Pour ce code d’exemple, j’utilise le célèbre texte Lorem Ipsum.
Le filigrane textuel est placé 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é un texte tourné, tracé avec des lettres rouges semi-transparentes de plus grande taille.
Le code d’exemple télécharge de manière asynchrone à la fois l’image et le texte depuis notre dépôt de code d’exemple. Bien sûr, vous pouvez utiliser une image locale et/ou lire le texte depuis 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 applications d’exemple qui couvrent les fonctionnalités mentionnées ci-dessus plus en détail. Prenez le temps de les consulter.