Questa pagina può contenere testo tradotto automaticamente.
Contenitori composti
I contenitori complessi svolgono un ruolo cruciale nella strutturazione e nell’organizzazione dei contenuti. Utilizzando un contenitore adeguato, puoi presentare facilmente testo e immagini in modo intuitivo.
È sicuramente possibile costruire un documento utilizzando solo semplici contenitori di testo e immagini. Tuttavia, esistono requisiti difficili o impossibili da implementare solo con contenitori semplici. I contenitori composti aiutano in questi casi. Inoltre, i contenitori complessi aiutano a raggiungere i tuoi obiettivi con meno codice.
Utilizza i metodi della classe LayoutContainer
per aggiungere contenitori complessi come Row e
Column alle pagine dei documenti. Utilizzando questi
contenitori, puoi implementare altri contenitori come griglie ed elenchi. Esistono anche i metodi
Inlined
e Layers
per casi meno comuni ma comunque importanti.
Questo articolo fa parte di una serie sull'API Layout per la generazione di PDF. Se sei nuovo all'API, leggi prima la parte Introduzione all'API Layout.
9.5.17615-dev 9.5.17615-devNe sono passati 14,813 Download totali di NuGet 4,924,084
Row
I contenitori Row offrono spazio per elementi disposti orizzontalmente su un'unica riga. Ogni elemento in una riga è un contenitore. Ciò significa che puoi inserire contenuti di diversi tipi in una riga. Puoi specificare la spaziatura tra gli elementi utilizzando il metodo Spacing.
Tutti gli elementi in fila hanno la stessa altezza. La libreria utilizza l'altezza dell'elemento più alto come altezza della riga. Esistono tre modi per specificare la larghezza di un elemento. Devi sceglierne uno quando crei l'oggetto. Una riga può contenere elementi creati in diversi modi.
Il metodo Row.AutoItem crea un elemento senza una
larghezza specificata esplicitamente. Per tali elementi, la biblioteca calcola la dimensione
intrinseca del loro contenuto. La larghezza del contenuto calcolata corrisponde alla larghezza
dell'articolo. Tieni presente che gli elementi creati con AutoItem
non vanno a capo nelle righe
lunghe.
Utilizza il metodo ConstantItem per creare un elemento con larghezza pari a un numero esatto di punti.
Il RelativeItem è utile quando non conosci la
larghezza esatta degli elementi nella riga e non vuoi utilizzare dimensioni intrinseche. Puoi
invece specificare larghezze relative per gli elementi nella riga. Il metodo accetta il numero di
parti che l'articolo dovrebbe occupare. Il numero totale di parti è la somma di tutti i numeri in
tutte le chiamate RelativeItem
in questa riga.
Ad esempio, se è presente una chiamata RelativeItem
, il numero non è importante. L'articolo
occuperà tutta la larghezza disponibile. Per due o più elementi, i numeri definiscono la
proporzione.
row.RelativeItem(2)
row.RelativeItem(3)
row.RelativeItem(1)
Tutti gli elementi creati con il codice precedente richiedono 6 parti (2 + 3 + 1 = 6
). I singoli
elementi occupano rispettivamente 2 parti su 6, 3 su 6 e 1 su 6.
L'API Layout utilizza la seguente formula per calcolare la larghezza di una parte:
PartWidth = (RowWidth - AutoWidth - ConstantWidth) / TotalParts
Dove:
RowWidth
= larghezza del contenitore di righe
AutoWidth
= larghezza di tutti gli elementi creati con il metodo "AutoItem"
ConstantWidth
= larghezza di tutti gli elementi creati con il metodo ConstantItem
Ecco un esempio che crea una riga con elementi di tutti e tre i tipi.
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]);
});
}
});
}));
Puoi vedere il risultato del codice in compounds-row.pdf.
Column
Per disporre gli elementi verticalmente, uno dopo l'altro, utilizza un contenitore Column. Ogni elemento in una colonna è un contenitore. Per questo motivo, puoi inserire contenuti di diversi tipi in una colonna.
La larghezza di ogni elemento è uguale alla larghezza della colonna. L'altezza di ciascun articolo
dipende dal contenuto e dalle proprietà dell'articolo. I contenitori Column
supportano il paging,
quindi il componente aggiuntivo Layout può eseguire il rendering degli elementi di una colonna su
più di una pagina.
Per impostazione predefinita, un contenitore Column
non ha contenuto di intestazione o piè di
pagina. Utilizza i metodi Header e
Footer per accedere e configurare i contenitori
corrispondenti. Quando gli elementi di colonna occupano più di una pagina, la libreria ripete sia
le intestazioni che i piè di pagina su ogni pagina.
Utilizza il metodo Spacing per aggiungere spazio verticale tra gli elementi della colonna. Tieni presente che la libreria non applica la spaziatura tra l'intestazione e il primo elemento. La libreria inoltre non aggiunge spazio prima del piè di pagina.
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);
});
}));
Puoi vedere il risultato del codice in compounds-column.pdf.
Griglia
I layout a griglia organizzano gli elementi in colonne e righe. Sotto questo aspetto le griglie sono simili alle tabelle. L'API Layout non fornisce un tipo di contenitore speciale per le griglie. Puoi implementare un layout a griglia utilizzando i contenitori Column e Row.
È utile pensare a una griglia come a una colonna, in cui ciascuno dei suoi elementi è una riga. Sia
i contenitori Column
che quelli Row
offrono la possibilità di impostare la spaziatura tra gli
elementi. Puoi avere un'intestazione e un piè di pagina, se lo desideri.
Ogni riga può avere un layout indipendente. Può esserci un numero diverso di elementi in ciascuna riga. Gli articoli possono avere larghezza e altezza diverse. È possibile aggiungere spazio aggiuntivo prima, dopo o tra gli elementi di una riga. Usa oggetti senza contenuto e decorazioni per questo.
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);
});
});
}));
Puoi vedere il risultato del codice in compounds-grid.pdf.
Elenchi
Gli elenchi migliorano la leggibilità suddividendo le informazioni in punti concisi. Gli elementi dell'elenco possono contenere numeri, punti elenco e altri simboli accanto al testo al loro interno. Puoi facilmente implementare un layout di elenco utilizzando i contenitori Column e Row. L'API Layout non fornisce un tipo di contenitore speciale per gli elenchi.
Controlla il codice di esempio che crea un elenco di mesi per stagione. Tieni presente che l'elenco ha un'intestazione. Se gli elementi contengono testo che può andare a capo nella riga successiva, utilizza il metodo RelativeItem o ConstantItem per la parte di testo dell'elemento.
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);
});
}
});
}));
Puoi vedere il risultato del codice in compounds-list.pdf.
Table
I layout di tabella organizzano gli elementi in colonne e righe. Il tipo di contenitore Table fornisce un ampio set di funzionalità e può aiutarti con i casi più sofisticati. Leggi tutte le funzionalità nell'articolo Contenitore Table.
InlineContainer
Puoi riempire un contenitore con una raccolta di altri contenitori. Inizia chiamando il metodo
LayoutContainer.Inlined
. Quindi chiama il metodo
Item dell
InlineContainer fornito per aggiungere
contenitori secondari.
Il componente aggiuntivo Layout mette i contenitori in fila uno dopo l'altro. Se non c'è spazio per
inserire un elemento, la libreria inizia una nuova riga. Utilizza i metodi
Spacing/HorizontalSpacing/VerticalSpacing
per aggiungere spazio tra gli elementi.
È possibile influenzare la posizione degli elementi nel contenitore utilizzando i metodi di
allineamento. I metodi AlignTop/AlignMiddle/AlignBottom
allineano gli elementi verticalmente. Per
la direzione orizzontale, utilizzare i metodi AlignLeft/AlignCenter/AlignRight/AlignJustify
.
C'è un caso speciale. Il metodo AlignSpaceAround che allinea gli elementi orizzontalmente. Aggiunge inoltre spaziatura extra prima del primo elemento e dopo l'ultimo elemento.
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);
});
}));
Puoi vedere il risultato del codice in compounds-inlined.pdf.
LayerContainer
Potrebbe essere necessario inserire del contenuto sotto e/o sopra il contenuto della pagina principale. Il caso d'uso ovvio è aggiungere una filigrana sopra le pagine PDF.
Per prima cosa, ottieni un oggetto LayerContainer chiamando il metodo LayoutContainer.Layers. Dato l'oggetto, puoi iniziare ad aggiungere livelli. La chiamata al metodo Layer aggiunge un livello secondario. Chiama il metodo PrimaryLayer per aggiungere il livello di contenuto principale. È necessario aggiungere esattamente un livello primario.
L'API Layout comporrà i livelli nello stesso ordine in cui li crei. I livelli aggiunti prima del livello primario andranno in secondo piano. Tutti i livelli aggiunti dopo il livello primario andranno sopra il contenuto principale. Il contenitore ripete i livelli secondari su tutte le pagine occupate dal contenuto principale.
Ecco un codice di esempio su come aggiungere filigrane alle pagine 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);
});
}));
Puoi vedere il risultato del codice in compounds-layers.pdf.
Filigrane
Uno dei requisiti comuni è aggiungere la filigrana al PDF. Il requisito può esistere per una serie di ragioni. È possibile aggiungere una filigrana al PDF per identificarne la proprietà o per evidenziare la riservatezza o la sensibilità delle informazioni nel PDF.
Un approccio per applicare la filigrana ai PDF consiste nell'utilizzare i livelli. Vedere l'esempio nella sezione precedente. Lascia che ti mostri un altro approccio.
Utilizzerò lo sfondo della pagina e i contenitori in primo piano per filigranare i PDF. Il componente aggiuntivo Layout ripete questi contenitori nelle pagine successive. Ogni pagina con contenuto del documento principale conterrà anche contenitori di sfondo e di primo piano. Questo li rende adatti al compito.
Inizio aggiungendo un'immagine al contenitore di sfondo. Puoi aggiungere il tuo logo al PDF allo stesso modo. L'immagine apparirà dietro il contenuto della pagina. Non importa quante pagine del tuo documento utilizzano l'immagine di sfondo. L'API aggiungerà solo una copia dei byte dell'immagine al PDF generato.
Il contenuto del documento principale può essere qualsiasi cosa. Per questo codice di esempio utilizzo il famoso testo Lorem Ipsum.
La filigrana del testo va nel contenitore in primo piano. Il testo stesso può essere qualsiasi cosa e puoi utilizzare qualsiasi colore o carattere. Ho utilizzato il testo ruotato disegnato con lettere rosse semitrasparenti di dimensione maggiore.
Il codice di esempio scarica in modo asincrono sia l'immagine che il testo dal nostro repository di codice di esempio. Naturalmente è possibile utilizzare un'immagine locale e/o leggere il testo da un file.
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);
});
});
Puoi vedere il risultato del codice in compounds-watermarks.pdf.
Codice d'esempio
Abbiamo alcune app di esempio che coprono le funzionalità sopra menzionate in modo più dettagliato. Per favore, dedica un po' di tempo a controllarli.