| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- using System.Collections.Generic;
- using System.Globalization;
- using System.Linq;
- using NUnit.Framework;
- using QuestPDF.Elements;
- using QuestPDF.Examples.Engine;
- using QuestPDF.Fluent;
- using QuestPDF.Helpers;
- using QuestPDF.Infrastructure;
- namespace QuestPDF.Examples
- {
- public class OrderItem
- {
- public string ItemName { get; set; } = Placeholders.Label();
- public int Price { get; set; } = Placeholders.Random.Next(1, 11) * 10;
- public int Count { get; set; } = Placeholders.Random.Next(1, 11);
- }
- public struct OrdersTableState
- {
- public int ShownItemsCount { get; set; }
- }
-
- public class OptimizedOrdersTable : IDynamicComponent<OrdersTableState>
- {
- private ICollection<OrderItem> Items { get; }
- public OrdersTableState State { get; set; }
- public OptimizedOrdersTable(ICollection<OrderItem> items)
- {
- Items = items;
- State = new OrdersTableState
- {
- ShownItemsCount = 0
- };
- }
-
- public DynamicComponentComposeResult Compose(DynamicContext context)
- {
- var header = ComposeHeader(context);
- var sampleFooter = ComposeFooter(context, Enumerable.Empty<OrderItem>());
- var decorationHeight = header.Size.Height + sampleFooter.Size.Height;
-
- var rows = GetItemsForPage(context, decorationHeight).ToList();
- var footer = ComposeFooter(context, rows.Select(x => x.Item));
- var content = context.CreateElement(container =>
- {
- container.MinimalBox().Decoration(decoration =>
- {
- decoration.Before().Element(header);
- decoration.Content().Column(column =>
- {
- foreach (var row in rows)
- column.Item().Element(row.Element);
- });
- decoration.After().Element(footer);
- });
- });
- State = new OrdersTableState
- {
- ShownItemsCount = State.ShownItemsCount + rows.Count
- };
- return new DynamicComponentComposeResult
- {
- Content = content,
- HasMoreContent = State.ShownItemsCount < Items.Count
- };
- }
- private static IDynamicElement ComposeHeader(DynamicContext context)
- {
- return context.CreateElement(element =>
- {
- element
- .Width(context.AvailableSize.Width)
- .BorderBottom(1)
- .BorderColor(Colors.Grey.Darken2)
- .Padding(5)
- .DefaultTextStyle(TextStyle.Default.SemiBold())
- .Row(row =>
- {
- row.ConstantItem(30).Text("#");
- row.RelativeItem().Text("Item name");
- row.ConstantItem(50).AlignRight().Text("Count");
- row.ConstantItem(50).AlignRight().Text("Price");
- row.ConstantItem(50).AlignRight().Text("Total");
- });
- });
- }
-
- private static IDynamicElement ComposeFooter(DynamicContext context, IEnumerable<OrderItem> items)
- {
- var total = items.Sum(x => x.Count * x.Price);
- return context.CreateElement(element =>
- {
- element
- .Width(context.AvailableSize.Width)
- .Padding(5)
- .AlignRight()
- .DefaultTextStyle(TextStyle.Default.FontSize(14).SemiBold())
- .Text($"Subtotal: {total}$");
- });
- }
-
- private IEnumerable<(OrderItem Item, IDynamicElement Element)> GetItemsForPage(DynamicContext context, float decorationHeight)
- {
- var totalHeight = decorationHeight;
- foreach (var index in Enumerable.Range(State.ShownItemsCount, Items.Count - State.ShownItemsCount))
- {
- var item = Items.ElementAt(index);
-
- var element = context.CreateElement(content =>
- {
- content
- .Width(context.AvailableSize.Width)
- .BorderBottom(1)
- .BorderColor(Colors.Grey.Lighten2)
- .Padding(5)
- .Row(row =>
- {
- row.ConstantItem(30).Text((index + 1).ToString(CultureInfo.InvariantCulture));
- row.RelativeItem().Text(item.ItemName);
- row.ConstantItem(50).AlignRight().Text(item.Count.ToString(CultureInfo.InvariantCulture));
- row.ConstantItem(50).AlignRight().Text($"{item.Price}$");
- row.ConstantItem(50).AlignRight().Text($"{item.Count*item.Price}$");
- });
- });
- var elementHeight = element.Size.Height;
- // it is important to use the Size.Epsilon constant to avoid floating point comparison issues
- if (totalHeight + elementHeight > context.AvailableSize.Height + Size.Epsilon)
- break;
-
- totalHeight += elementHeight;
- yield return (item, element);
- }
- }
- }
-
- public static class DynamicOptimizedExamples
- {
- [Test]
- public static void Dynamic()
- {
- RenderingTest
- .Create()
- .PageSize(PageSizes.A5)
- .ProducePdf()
- .ShowResults()
- .Render(container =>
- {
- var items = Enumerable.Range(0, 25).Select(x => new OrderItem()).ToList();
-
- container
- .Background(Colors.White)
- .Padding(25)
- .Decoration(decoration =>
- {
- decoration
- .Before()
- .PaddingBottom(5)
- .Text(text =>
- {
- text.DefaultTextStyle(TextStyle.Default.SemiBold().FontColor(Colors.Blue.Darken2).FontSize(16));
- text.Span("Page ");
- text.CurrentPageNumber();
- text.Span(" of ");
- text.TotalPages();
- });
-
- decoration
- .Content()
- .Dynamic(new OptimizedOrdersTable(items));
- });
- });
- }
- }
- }
|