Diese Seite kann automatisch übersetzten Text enthalten.

Verbundbehälter

Komplexe Container spielen eine entscheidende Rolle bei der Strukturierung und Organisation von Inhalten. Durch die Verwendung eines geeigneten Containers können Sie Text und Bilder einfach und benutzerfreundlich präsentieren.

Es ist durchaus möglich, ein Dokument nur mit einfachen Text- und Bildcontainern zu erstellen. Allerdings gibt es Anforderungen, die sich nur mit einfachen Containern nur schwer oder gar nicht umsetzen lassen. In solchen Fällen helfen zusammengesetzte Container. Außerdem helfen komplexe Container dabei, Ihre Ziele mit weniger Code zu erreichen.

Verbundbehälter

Verwenden Sie Methoden der Klasse LayoutContainer, um komplexe Container wie Row und Column zu Dokumentseiten hinzuzufügen. Mit diesen Containern können Sie andere Container wie Raster und Listen implementieren. Es gibt auch die Methoden Inlined und Layers für weniger gebräuchliche, aber dennoch wichtige Fälle.

Dieser Artikel ist Teil einer Serie über die Layout-API für die PDF-Generierung. Wenn Sie mit der API noch nicht vertraut sind, lesen Sie zuerst den Teil Erste Schritte mit der Layout-API.

Docotic.Pdf-Bibliothek 9.5.17664-dev Layout-Add-on 9.5.17664-dev
Regressionstests 14,820 bestanden NuGet-Downloads insgesamt 4,998,853

Row

Row-Container bieten Platz für horizontal in einer Zeile angeordnete Elemente. Jedes Element in einer Zeile ist ein Container. Das bedeutet, dass Sie Inhalte unterschiedlichen Typs in einer Zeile unterbringen können. Sie können den Abstand zwischen den Elementen mit der Methode Spacing festlegen.

Alle Elemente in einer Reihe haben die gleiche Höhe. Die Bibliothek verwendet die Höhe des höchsten Elements als Höhe der Reihe. Es gibt drei Möglichkeiten, die Breite eines Elements anzugeben. Sie müssen beim Erstellen des Elements eine auswählen. Eine Reihe kann Elemente enthalten, die auf unterschiedliche Weise erstellt wurden.

Die Methode Row.AutoItem erstellt ein Element ohne explizit angegebene Breite. Für solche Elemente berechnet die Bibliothek die tatsächliche Größe ihres Inhalts. Die berechnete Inhaltsbreite ist die Breite des Elements. Bitte beachten Sie, dass mit AutoItem erstellte Elemente lange Zeilen nicht umbrechen.

Verwenden Sie die Methode ConstantItem, um ein Element mit einer Breite zu erstellen, die einer genauen Anzahl von Punkten entspricht.

Das RelativeItem ist praktisch, wenn Sie die genaue Breite der Elemente in der Zeile nicht kennen und keine intrinsischen Größen verwenden möchten. Stattdessen können Sie relative Breiten für Elemente in der Zeile angeben. Die Methode akzeptiert die Anzahl der Teile, die das Element einnehmen soll. Die Gesamtzahl der Teile ist die Summe aller Zahlen in allen RelativeItem-Aufrufen in dieser Zeile.

Wenn es beispielsweise einen RelativeItem-Aufruf gibt, ist die Zahl nicht wichtig. Das Element nimmt die gesamte verfügbare Breite ein. Bei zwei oder mehr Elementen definieren die Zahlen die Proportionen.

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

Alle mit dem obigen Code erstellten Elemente bestehen aus 6 Teilen (2 + 3 + 1 = 6). Einzelne Elemente nehmen jeweils 2 von 6, 3 von 6 und 1 von 6 Teilen ein.

Die Layout-API verwendet die folgende Formel, um die Breite eines Teils zu berechnen:

PartWidth = (RowWidth - AutoWidth - ConstantWidth) / TotalParts

wobei:
RowWidth = Breite des Zeilencontainers,
AutoWidth = Breite aller mit der Methode AutoItem erstellten Elemente,
ConstantWidth = Breite aller mit der Methode ConstantItem erstellten Elemente.

Hier ist ein Beispiel, das eine Zeile mit Elementen aller drei Arten erstellt.

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]);
                    });
            }
        });
}));

Das Ergebnis des Codes können Sie in compounds-row.pdf sehen.

Column

Um Elemente vertikal hintereinander anzuordnen, verwenden Sie einen Column-Container. Jedes Element in einer Spalte ist ein Container. Dadurch können Sie Inhalte unterschiedlichen Typs in einer Spalte platzieren.

Die Breite jedes Elements entspricht der Spaltenbreite. Die Höhe jedes Elements hängt vom Inhalt und den Eigenschaften des Elements ab. Column-Container unterstützen die Seitennummerierung, sodass das Layout-Add-on Elemente einer Spalte auf mehreren Seiten darstellen kann.

Standardmäßig hat ein Column-Container keinen Kopf- oder Fußzeileninhalt. Verwenden Sie die Methoden Header und Footer, um auf die entsprechenden Container zuzugreifen und sie einzurichten. Wenn Spaltenelemente mehr als eine Seite einnehmen, wiederholt die Bibliothek sowohl Kopf- als auch Fußzeilen auf jeder Seite.

Verwenden Sie die Methode Spacing, um einen vertikalen Abstand zwischen den Spaltenelementen hinzuzufügen. Bitte beachten Sie, dass die Bibliothek keinen Abstand zwischen der Kopfzeile und dem ersten Element anwendet. Die Bibliothek fügt auch keinen Abstand vor der Fußzeile hinzu.

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);
        });
}));

Das Ergebnis des Codes können Sie in compounds-column.pdf sehen.

Raster

Rasterlayouts organisieren Elemente in Spalten und Zeilen. Raster sind in dieser Hinsicht Tabellen ähnlich. Die Layout-API bietet keinen speziellen Containertyp für Raster. Sie können ein Rasterlayout mit den Containern Column und Row implementieren.

Es ist hilfreich, sich ein Raster als eine Spalte vorzustellen, wobei jedes seiner Elemente eine Zeile darstellt. Sowohl die Container Column als auch Row bieten die Möglichkeit, den Abstand zwischen den Elementen festzulegen. Sie können eine Kopf- und eine Fußzeile haben, wenn Sie möchten.

Jede Zeile kann ein unabhängiges Layout haben. Jede Zeile kann eine unterschiedliche Anzahl von Elementen enthalten. Elemente können unterschiedliche Breiten und Höhen haben. Es ist möglich, vor, nach oder zwischen Elementen in einer Zeile zusätzlichen Platz einzufügen. Verwenden Sie hierfür Elemente ohne Inhalt und Dekoration.

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);
        });
    });
}));

Das Ergebnis des Codes können Sie in compounds-grid.pdf sehen.

Listen

Listen verbessern die Lesbarkeit, indem sie Informationen in prägnante Punkte aufteilen. Listenelemente können Zahlen, Aufzählungszeichen und andere Symbole neben dem darin enthaltenen Text enthalten. Sie können ein Listenlayout problemlos mit den Containern Column und Row implementieren. Die Layout-API bietet keinen speziellen Containertyp für Listen.

Sehen Sie sich den Beispielcode an, der eine Liste von Monaten nach Jahreszeiten erstellt. Bitte beachten Sie, dass die Liste eine Kopfzeile hat. Wenn Elemente Text enthalten, der in die nächste Zeile umbrochen werden kann, verwenden Sie für den Textteil des Elements entweder die Methode RelativeItem oder die Methode ConstantItem.

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);
            });
        }
    });
}));

Das Ergebnis des Codes können Sie in compounds-list.pdf sehen.

Table

Tabellenlayouts organisieren Elemente in Spalten und Zeilen. Der Containertyp Table bietet eine umfangreiche Reihe von Funktionen und kann Ihnen bei den anspruchsvollsten Fällen helfen. Lesen Sie mehr über alle Funktionen im Artikel Table-Container.

InlineContainer

Sie können einen Container mit einer Sammlung anderer Container füllen. Beginnen Sie mit dem Aufruf der Methode LayoutContainer.Inlined. Rufen Sie dann die Methode Item des bereitgestellten InlineContainer auf, um untergeordnete Container hinzuzufügen.

Das Layout-Add-on platziert Container in einer Reihe hintereinander. Wenn kein Platz für ein Element vorhanden ist, beginnt die Bibliothek eine neue Reihe. Verwenden Sie die Methoden Spacing/HorizontalSpacing/VerticalSpacing, um etwas Abstand zwischen den Elementen hinzuzufügen.

Sie können die Position von Elementen im Container mithilfe von Ausrichtungsmethoden beeinflussen. Die Methoden AlignTop/AlignMiddle/AlignBottom richten Elemente vertikal aus. Für die horizontale Richtung verwenden Sie die Methoden AlignLeft/AlignCenter/AlignRight/AlignJustify.

Es gibt einen Sonderfall. Die Methode AlignSpaceAround richtet Elemente horizontal aus. Sie fügt außerdem zusätzlichen Abstand vor dem ersten und nach dem letzten Element hinzu.

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);
    });
}));

Das Ergebnis des Codes können Sie in compounds-inlined.pdf sehen.

LayerContainer

Möglicherweise müssen Sie Inhalt unter und/oder über den Inhalt der Hauptseite setzen. Der offensichtlichste Anwendungsfall ist das Hinzufügen eines Wasserzeichens über PDF-Seiten.

Holen Sie sich zunächst ein LayerContainer-Objekt, indem Sie die Methode LayoutContainer.Layers aufrufen. Wenn das Objekt vorhanden ist, können Sie mit dem Hinzufügen von Ebenen beginnen. Durch Aufrufen der Methode Layer wird eine sekundäre Ebene hinzugefügt. Rufen Sie die Methode PrimaryLayer auf, um die Hauptinhaltsebene hinzuzufügen. Sie müssen genau eine primäre Ebene hinzufügen.

Die Layout-API erstellt die Ebenen in derselben Reihenfolge, in der Sie sie erstellen. Ebenen, die vor der primären Ebene hinzugefügt werden, werden in den Hintergrund verschoben. Alle Ebenen, die nach der primären Ebene hinzugefügt werden, werden über den Hauptinhalt verschoben. Der Container wiederholt die sekundären Ebenen auf allen Seiten, die vom Hauptinhalt belegt werden.

Hier ist ein Beispielcode zum Hinzufügen von Wasserzeichen zu PDF-Seiten.

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);
        });
}));

Das Ergebnis des Codes können Sie in compounds-layers.pdf sehen.

Wasserzeichen

Eine der häufigsten Anforderungen besteht darin, PDFs mit Wasserzeichen zu versehen. Diese Anforderung kann aus verschiedenen Gründen bestehen. Sie können PDFs mit Wasserzeichen versehen, um den Eigentümer zu identifizieren oder auf die Vertraulichkeit oder Sensibilität der Informationen in der PDF hinzuweisen.

Eine Möglichkeit, PDFs mit Wasserzeichen zu versehen, besteht in der Verwendung von Ebenen. Siehe das Beispiel im vorherigen Abschnitt. Ich zeige Ihnen eine andere Möglichkeit.

Ich werde Seitenhintergrund- und Vordergrundcontainer verwenden, um PDFs mit Wasserzeichen zu versehen. Das Layout-Add-on wiederholt diese Container auf den nächsten Seiten. Jede Seite mit primärem Dokumentinhalt wird auch Hintergrund- und Vordergrundcontainer enthalten. Dadurch sind sie für die Aufgabe geeignet.

Ich beginne damit, dem Hintergrundcontainer ein Bild hinzuzufügen. Sie können Ihr Logo auf die gleiche Weise zu PDF hinzufügen. Das Bild wird hinter dem Seiteninhalt angezeigt. Es spielt keine Rolle, wie viele Seiten Ihres Dokuments das Hintergrundbild verwenden. Die API fügt dem generierten PDF nur eine Kopie der Bildbytes hinzu.

Der primäre Dokumentinhalt kann alles sein. Für diesen Beispielcode verwende ich den berühmten Lorem Ipsum-Text.

Das Textwasserzeichen wird in den Vordergrundcontainer eingefügt. Der Text selbst kann beliebig sein und Sie können jede beliebige Farbe oder Schriftart verwenden. Ich habe gedrehten Text verwendet, der mit halbtransparenten roten Buchstaben in größerer Größe gezeichnet wurde.

Der Beispielcode lädt sowohl das Bild als auch den Text asynchron aus unserem Beispielcode-Repository herunter. Natürlich können Sie ein lokales Bild verwenden und/oder den Text aus einer Datei lesen.

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);
    });
});

Das Ergebnis des Codes können Sie in compounds-watermarks.pdf sehen.

Beispielcode

Wir haben einige Beispiel-Apps, die die oben genannten Funktionen ausführlicher behandeln. Bitte nehmen Sie sich etwas Zeit und sehen Sie sie sich an.