Esta página puede contener texto traducido automáticamente.
Contenedores y su contenido
Un documento es un conjunto de páginas. Cada página, a su vez, es un conjunto de fragmentos de contenido. Como quizá ya sepa, la clase PageLayout proporciona contenedores para el contenido principal y adicional. Pero ¿qué hacer con estos contenedores?

Los contenedores ayudan a organizar el contenido en las páginas. Todo lo que coloque en una página debe ir en un contenedor. Si el contenido es lo bastante grande, un contenedor puede ocupar espacio en más de una página.
Puede colocar algo de texto o una imagen en un contenedor. Para fines de alineación y posicionamiento, puede colocar un contenedor dentro de otro contenedor. Hay contenedores que ofrecen espacio para más de un fragmento de contenido.
Los contenedores en una página se representan mediante objetos de la clase LayoutContainer. Use esta clase para configurar el tamaño, la posición, el contenido y el proceso de renderizado de sus contenedores.
Este artículo forma parte de una serie sobre Layout API para la generación de PDF. Si es nuevo en la API, lea primero la parte Getting Started with Layout API.
Cómo funcionan los contenedores
Empieza obteniendo un contenedor. Por ejemplo, llamando al método PageLayout.Content. Este método devolverá un contenedor que no ocupa espacio y no tiene contenido ni propiedades configuradas. Use los métodos de la clase LayoutContainer para configurar el contenedor.
Lo muy importante que hay que entender es que todos los métodos de LayoutContainer colocan contenido en el contenedor. Cuando agrega texto al contenedor, eso es lo esperado. Pero ¿qué pasa a ser el contenido cuando establece un sangrado o un ancho?
Cuando establece una propiedad de un contenedor, la biblioteca crea un nuevo contenedor con la propiedad especificada. El nuevo contenedor se convierte en el contenido del contenedor original. La biblioteca devuelve el contenedor anidado como resultado del método.
Las propiedades de los contenedores anidados afectan a los contenedores padre y viceversa. Por ejemplo, el ancho de un contenedor anidado afecta al tamaño de los contenedores padre. El estilo de texto predeterminado de un contenedor padre afecta al texto de los contenedores anidados. El complemento Layout usa la jerarquía de contenedores y sus propiedades para construir el diseño resultante.
El resultado del siguiente código puede sorprenderle, pero dedique un tiempo a analizarlo. El código ilustra cómo funcionan los contenedores anidados.
PdfDocumentBuilder.Create().Generate("containers-how.pdf", doc => doc.Pages(page =>
{
page.Size(150, 150);
page.Content()
.Background(new PdfRgbColor(235, 64, 52)) // rojo
.PaddingTop(50)
.Background(new PdfRgbColor(187, 237, 237)) // azul
.PaddingRight(50)
.Background(new PdfRgbColor(15, 130, 9)) // verde
.PaddingBottom(50)
.Background(new PdfRgbColor(250, 123, 5)) // naranja
.PaddingLeft(50)
.Background(new PdfRgbColor(204, 204, 204)); // gris
}));
Decoración
El diseño de documentos implica más que organizar texto e imágenes. Un documento bien diseñado crea no solo una comunicación eficaz, sino también visualmente atractiva.
Con Layout API, puede aplicar un color de fondo a cualquier contenedor. Esto ayuda a establecer una jerarquía dentro del contenido. También puede definir límites aplicando bordes. Use líneas verticales y horizontales para separar elementos de contenido.
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 }));
}));
La API admite colores opacos y semitranslúcidos en los espacios de color Gray, RGB y CMYK. Además de líneas continuas, Layout API ofrece compatibilidad con líneas que usan dash patterns.
El resultado del código anterior está en containers-decor.pdf.
Contenido
Veamos qué proporciona la clase LayoutContainer para organizar contenido.
Text
Para agregar texto a un contenedor, use uno de los métodos Text.
Si todo el texto usa el mismo estilo, use la versión abreviada simple del método. Esa versión acepta una cadena y devuelve un objeto TextSpan. Puede usar ese objeto para configurar el estilo de texto del fragmento.
Hay otra versión del método Text que acepta un delegado del tipo Action<TextContainer>. Use esa versión para tener fragmentos con estilos distintos dentro de un solo bloque de texto. El TextContainer proporciona métodos para insertar imágenes y otros elementos entre fragmentos de texto. Hay otras características avanzadas, como la posibilidad de establecer una distancia entre párrafos.
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());
});
}));
Puede ver el resultado del código en containers-text.pdf.
Image
Layout API proporciona métodos para crear objetos Image a partir de datos de imagen en un archivo o un flujo. Cualquier objeto Image puede servir como contenido de un contenedor. Puede usar el mismo objeto Image en varios contenedores. Hay distintos modos de contenido que afectan al aspecto de la imagen dentro del contenedor.
La biblioteca solo puede cargar imágenes en formatos rasterizados: PNG, JPEG, JPEG 2000, BMP, GIF y 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
Las columnas ofrecen espacio para un número ilimitado de elementos colocados verticalmente uno tras otro. Puede usar elementos de cualquier tipo dentro de una columna. Por ejemplo, una columna puede contener elementos de imagen y texto. El ancho de cada elemento es igual al ancho de la columna. La altura de cada elemento depende del contenido y las propiedades del elemento.
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);
}
});
}));
Puede ver el resultado del código en containers-column.pdf.
Lea el artículo Contenedores compuestos para obtener información detallada sobre las características del contenedor Column.
Row
Los contenedores Row ayudan a organizar un número ilimitado de elementos horizontalmente. Cada elemento en una fila es un contenedor. Debido a ello, puede colocar contenido de distintos tipos en una fila.
var rowItems = new[] { "three", "two", "one" };
PdfDocumentBuilder.Create().Generate("containers-row.pdf", doc => doc.Pages(page =>
{
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);
}
});
}));
Puede ver el resultado del código en containers-row.pdf.
El artículo Contenedores compuestos contiene información detallada sobre los contenedores Row.
Table
Use contenedores Table para maquetar sus datos más complejos. Empiece definiendo al menos una columna y luego complete columnas y filas llamando al método Cell varias veces.
Las tablas pueden tener un encabezado y un pie de página. Las celdas de una tabla pueden abarcar más de una columna y/o fila. Aquí hay un código que agrega una tabla simple.
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}");
}
});
}));
El resultado del código está en containers-table.pdf.
Lea sobre todas las características del contenedor Table en el artículo Contenedor de tabla.
Inlined
El tipo de contenedor InlineContainer ofrece una forma cómoda de rellenar un área con elementos de una colección de contenedores. Solo agrega elementos uno tras otro y la biblioteca los coloca en una fila, uno tras otro. Si no hay espacio para colocar un elemento, la biblioteca comienza una nueva fila.
Hay más información sobre los contenedores InlineContainer en el artículo Contenedores compuestos.
Layers
Hay casos en los que conviene colocar contenido en varias capas. El tipo de contenedor LayerContainer sirve exactamente para este propósito. Debe definir exactamente una capa principal y cualquier número de capas no principales. Layout API compondrá las capas en el mismo orden en que las cree.
Lea el artículo Contenedores compuestos para obtener más detalles sobre el tipo LayerContainer.
Element
Este es un tipo especial de contenido. Puede crear un elemento dinámicamente y colocar el resultado en un contenedor.
Los elementos creados dinámicamente pueden proporcionar un diseño que depende del número de página, el tamaño y otras propiedades.