Эта страница может содержать автоматически переведенный текст.

Контейнеры и их содержимое

Документ представляет собой набор страниц. Каждая страница, в свою очередь, представляет собой набор фрагментов контента. Как вы, возможно, уже знаете, PageLayout предоставляет контейнеры для основного и дополнительного контента. Но что делать с этими контейнерами?

Контейнеры для содержимого страницы

Контейнеры помогают организовать контент на страницах. Все, что вы помещаете на страницу, должно попасть в контейнер. Если содержимое достаточно велико, контейнер может занимать место более чем на одной странице.

Вы можете поместить в контейнер текст или изображение. В целях выравнивания и позиционирования вы можете поместить контейнер внутрь другого контейнера. Существуют контейнеры, в которых можно разместить более одного фрагмента контента.

Контейнеры на странице представлены объектами класса LayoutContainer. Используйте этот класс для настройки размера, положения, содержимого и процесса рендеринга ваших контейнеров.

Эта статья - часть серии статей про Layout API для генерации PDF-файлов. Если вы новичок в работе с API, то сначала прочитайте часть Начало работы с Layout API.

Библиотека Docotic.Pdf 9.5.17615-dev Дополнение Layout 9.5.17615-dev
Регрессионные тесты 14,813 прошло Всего загрузок NuGet 4,924,084

Принцип работы контейнеров

Вы начинаете с получения контейнера. Например, вызвав метод 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)) // красный

        .PaddingTop(50)
        .Background(new PdfRgbColor(187, 237, 237)) // голубой

        .PaddingRight(50)
        .Background(new PdfRgbColor(15, 130, 9)) // зеленый

        .PaddingBottom(50)
        .Background(new PdfRgbColor(250, 123, 5)) // оранжевый

        .PaddingLeft(50)
        .Background(new PdfRgbColor(204, 204, 204)); // серый
}));

Украшение

Дизайн документа включает в себя больше, чем просто организацию текста и изображений. Правильно разработанный документ создает не только эффективную, но и визуально привлекательную коммуникацию.

С помощью 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

API Layout предоставляет методы для создания объектов 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.

Прочтите статью Составные контейнеры для получения подробной информации о функциях контейнера Column.

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.

Статья Составные контейнеры содержит подробную информацию о контейнерах Row.

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.

Обо всех возможностях контейнера Table читайте в статье Контейнер Table.

Inlined

Контейнер InlineContainer позволяет удобно заполнить область элементами из коллекции контейнеров. Вы просто добавляете элементы один за другим, а библиотека ставит их в ряд один за другим. Когда места для размещения нового элемента нет, библиотека начинает новую строку.

Дополнительную информацию о контейнерах InlineContainer можно найти в статье Составные контейнеры.

Layers

Бывают случаи, когда лучше размещать контент на нескольких слоях. Контейнер LayerContainer служит именно этой цели. Вы должны определить ровно один основной слой и любое количество неосновных. Layout API будет компоновать слои в том же порядке, в котором вы их создаете.

Прочтите Составные контейнеры для получения более подробной информации о типе LayerContainer.

Element

Это особый вид контента. Вы можете создать элемент динамически и поместить результат в контейнер.

Динамически создаваемые элементы могут иметь макет, который зависит от номера страницы, размера и других свойств.