该页面可以包含自动翻译的文本。

容器及其内容物

文档是一组页面。 每个页面本身都是一组内容片段。 您可能已经知道,PageLayout 为主要内容和附加内容提 供了容器。 但如何处理这些容器呢?

页面内容的容器

容器有助于组织页面上的内容。 您放在页面上的所有内容都必须放入容器中。 如果内容足够大,一个容器可以 占据多个页面的空间。

您可以将一些文本或图像放入容器中。 为了对齐和定位,您可以将一个容器放入另一个容器中。 有些容器可以 为多个内容提供空间。

页面上的容器由 LayoutContainer 类的对象表示。 使用此类来设置容器的大小、位置、内容和渲染过程。

本文是有关用于 PDF 生成的 Layout API 的系列文章的一部分。 如果您是 API 新手,请先阅读 Layout API入 门 部分。

Docotic.Pdf 库 9.4.17342 布局附加组件 9.4.17342
回归测试 14,727 通过 NuGet 总下载量 4,260,602

容器如何工作

您首先获得一个容器。 例如,通过调用 PageLayout.Content 方法。 此方法将返回一个不占用空间且没有设 置内容或属性的容器。 使用 LayoutContainer 类的方法来设置容器。

要理解的非常重要的一点是,所有 LayoutContainer 方法都将内容放入容器中。 当您向容器添加一些文 本时,这是预期的。 但是,当您设置缩进或宽度时,内容会变成什么呢?

当您设置容器属性时,库会创建一个具有指定属性的容器。 新容器成为原始容器的内容。 该库返回嵌套 容器作为该方法的结果。

嵌套容器的属性会影响父容器,反之亦然。 例如,嵌套容器的宽度会影响父容器的大小。 父容器的默认文本样 式会影响嵌套容器中的文本。 Layout 附加组件使用容器的层次结构及其属性来构建结果布局。

以下代码的结果 可能会让您感到惊讶,但请花一些时间分 析它。 该代码说明了嵌套容器的工作原理。

PdfDocumentBuilder.Create().Generate("containers-how.pdf", doc => doc.Pages(page =>
{
    page.Size(150, 150);
    page.Content()
        .Background(new PdfRgbColor(235, 64, 52)) // red

        .PaddingTop(50)
        .Background(new PdfRgbColor(187, 237, 237)) // blue

        .PaddingRight(50)
        .Background(new PdfRgbColor(15, 130, 9)) // green

        .PaddingBottom(50)
        .Background(new PdfRgbColor(250, 123, 5)) // orange

        .PaddingLeft(50)
        .Background(new PdfRgbColor(204, 204, 204)); // gray
}));

装饰

文档设计不仅仅涉及排列文本和图像。 正确设计的文档不仅能创造有效的沟通,而且还能产生视觉上吸引人的沟 通。

使用 Layout API,您可以将背景颜色应用于任何容器。 这有助于在内容中建立层次结构。 您还可以通过应用边 框来定义边界。 使用垂直线和水平线来分隔内容元素。

PdfDocumentBuilder.Create().Generate("containers-decor.pdf", doc => doc.Pages(page =>
{
    page.Size(150, 150);
    page.Content()
        .Background(new PdfRgbColor(250, 123, 5))
        .Border(b =>
        {
            b.Color(new PdfGrayColor(0), 50);
            b.Thickness(15);
        })
        .PaddingTop(74)
        .LineHorizontal(2)
            .Color(new PdfCmykColor(73, 45, 0, 4))
            .DashPattern(new PdfDashPattern(new double[] { 8, 2 }));
}));

该 API 支持 Gray、RGB 和 CMYK 颜色空间中的不透明和半透明颜色。 除了实线之外,Layout API 还支持使用 虚线图案的线条。

上述代码的结果在containers-decor.pdf中。

内容

让我们看看 LayoutContainer 类提供了什么来组织内容。

Text

要将一些文本添加到容器中,请使用 Text 方法之一。

如果所有文本都使用相同的样式,请使用该方法的简单速记版本。 该版本接受一个字符串并返回一个TextSpan 对象。 您可以使用该对象来设置跨度的文本样式。

还有另一个版本的 Text 方法接受 Action<TextContainer> 类型的委托。 使用该版本可以在一个文本块中 具有不同样式的跨度。 TextContainer 提供了在文本范围之间插入图像和其他元素的方法。 还有其他高级功 能,例如设置段落之间的距离的能力。

PdfDocumentBuilder.Create().Generate("containers-text.pdf", doc => doc.Pages(page =>
{
    page.Header().Text("This is a simple text span");

    page.Content().Text(t =>
    {
        t.Span("This line contains ");
        t.Span("some underlined text").Style(TextStyle.Parent.Underline());
    });
}));

您可以在 containers-text.pdf 中看到代码的结果。

Image

Layout API 提供了从文件或流中的图像数据创建 Image 对象的方法。 任何 Image 对象都可以作为容器的 内容。 您可以在多个容器中使用相同的 Image 对象。 有不同的内容模式会影响图像在容器内的外观。

该库只能加载光栅格式的图像:PNG、JPEG、JPEG 2000、BMP、GIF 和 TIFF。

PdfDocumentBuilder.Create().Generate("containers-image.pdf", doc =>
{
    var imageFile = new FileInfo(@"path-to-image.jpg");
    var image = doc.Image(imageFile);

    doc.Pages(pages =>
    {
        pages.Size(image.Width, image.Height);
        pages.Content().Image(image, ImageContentMode.FitArea);
    });
});

Column

列为无数个连续垂直放置的项目提供空间。 您可以在列中使用任何类型的项目。 例如,列可以包含图像和文本 项。 每个项目的宽度等于列宽。 每个项目的高度取决于项目的内容和属性。

PdfDocumentBuilder.Create().Generate("containers-column.pdf", doc => doc.Pages(page =>
{
    page.Content().Column(c =>
    {
        for (int i = 0; i < 10; i++)
        {
            PdfColor color = i % 2 == 0
                ? new PdfRgbColor(187, 237, 237)
                : new PdfGrayColor(66);

            c.Item().Background(color).Height(10 + i * 3);
        }
    });
}));

您可以在 containers-column.pdf 中看到代码的结 果。

Row

Row 容器有助于水平组织无限数量的项目。 一行中的每个项目都是一个容器。 因此,您可以将不同类型的内 容放在一行中。

PdfDocumentBuilder.Create().Generate("containers-row.pdf", doc => doc.Pages(page =>
{
    var rowItems = new[] { "three", "two", "one" };

    page.Content().Row(row =>
    {
        for (int index = 0; index < rowItems.Length; index++)
        {
            row.AutoItem().Text(rowItems[index]);

            if (index != rowItems.Length - 1)
                row.AutoItem().PaddingHorizontal(10).LineVertical(0.5);
        }
    });
}));

您可以在 containers-row.pdf 中看到代码的结果。

Table

使用 Table 容器来布局最复杂的数据。 首先定义至少一列,然后通过多次调用 Cell 方法来填充列和行。

表格可以有页眉和页脚。 表中的单元格可以跨越多列和/或多行。 这是添加一个简单表格的代码。

PdfDocumentBuilder.Create().Generate("containers-table.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.Cell()
                .Border(b => b.Thickness(0.5))
                .PaddingHorizontal(10)
                .Text($"{i + 1}");
        }
    });
}));

代码的结果在containers-table.pdf中。

Inlined

Inlined 容器提供了一种用容器集合中的项目填充区域的便捷方法。 您只需一个接一个地添加项目,库就会将 它们一个接一个地排成一行。 如果没有空间放置项目,库将开始一个新行。

Layers

在某些情况下,最好将内容放在多个层上。 Layers 容器正是用于此目的。 您必须准确定义一个主要层和任意 数量的非主要层。 Layout API 将按照您创建层的顺序组成层。

Element

这是一种特殊的内容。 您可以动态创建元素并将结果放入容器中。

动态创建的元素可以提供取决于页码、大小和其他属性的布局。