DynamicExamples.cs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. using System.Collections.Generic;
  2. using System.Linq;
  3. using NUnit.Framework;
  4. using QuestPDF.Elements;
  5. using QuestPDF.Examples.Engine;
  6. using QuestPDF.Fluent;
  7. using QuestPDF.Helpers;
  8. using QuestPDF.Infrastructure;
  9. namespace QuestPDF.Examples
  10. {
  11. public class OrderItem
  12. {
  13. public string ItemName { get; set; } = Placeholders.Label();
  14. public int Price { get; set; } = Placeholders.Random.Next(1, 11) * 10;
  15. public int Count { get; set; } = Placeholders.Random.Next(1, 11);
  16. }
  17. public class OrdersTable : IDynamicComponent
  18. {
  19. private ICollection<OrderItem> Items { get; }
  20. private ICollection<OrderItem> ItemsLeft { get; set; }
  21. public OrdersTable(ICollection<OrderItem> items)
  22. {
  23. Items = items;
  24. }
  25. public void Compose(DynamicContext context, IDynamicContainer container)
  26. {
  27. if (context.Operation == DynamicLayoutOperation.Reset)
  28. {
  29. ItemsLeft = new List<OrderItem>(Items);
  30. return;
  31. }
  32. var header = ComposeHeader(context);
  33. var sampleFooter = ComposeFooter(context, Enumerable.Empty<OrderItem>());
  34. var decorationHeight = header.Size.Height + sampleFooter.Size.Height;
  35. var rows = GetItemsForPage(context, decorationHeight).ToList();
  36. var footer = ComposeFooter(context, rows.Select(x => x.Item));
  37. if (ItemsLeft.Count > rows.Count)
  38. container.HasMoreContent();
  39. if (context.Operation == DynamicLayoutOperation.Draw)
  40. ItemsLeft = ItemsLeft.Skip(rows.Count).ToList();
  41. container.Box().Decoration(decoration =>
  42. {
  43. decoration.Header().Element(header);
  44. decoration.Content().Box().Stack(stack =>
  45. {
  46. foreach (var row in rows)
  47. stack.Item().Element(row.Element);
  48. });
  49. decoration.Footer().Element(footer);
  50. });
  51. }
  52. private IDynamicElement ComposeHeader(DynamicContext context)
  53. {
  54. return context.CreateElement(element =>
  55. {
  56. element
  57. .BorderBottom(1)
  58. .BorderColor(Colors.Grey.Darken2)
  59. .Padding(5)
  60. .Row(row =>
  61. {
  62. var textStyle = TextStyle.Default.SemiBold();
  63. row.ConstantColumn(30).Text("#", textStyle);
  64. row.RelativeColumn().Text("Item name", textStyle);
  65. row.ConstantColumn(50).AlignRight().Text("Count", textStyle);
  66. row.ConstantColumn(50).AlignRight().Text("Price", textStyle);
  67. row.ConstantColumn(50).AlignRight().Text("Total", textStyle);
  68. });
  69. });
  70. }
  71. private IDynamicElement ComposeFooter(DynamicContext context, IEnumerable<OrderItem> items)
  72. {
  73. var total = items.Sum(x => x.Count * x.Price);
  74. return context.CreateElement(element =>
  75. {
  76. element
  77. .Padding(5)
  78. .AlignRight()
  79. .Text($"Subtotal: {total}$", TextStyle.Default.Size(14).SemiBold());
  80. });
  81. }
  82. private IEnumerable<(OrderItem Item, IDynamicElement Element)> GetItemsForPage(DynamicContext context, float decorationHeight)
  83. {
  84. var totalHeight = decorationHeight;
  85. var counter = Items.Count - ItemsLeft.Count + 1;
  86. foreach (var orderItem in ItemsLeft)
  87. {
  88. var element = context.CreateElement(content =>
  89. {
  90. content
  91. .BorderBottom(1)
  92. .BorderColor(Colors.Grey.Lighten2)
  93. .Padding(5)
  94. .Row(row =>
  95. {
  96. row.ConstantColumn(30).Text(counter++);
  97. row.RelativeColumn().Text(orderItem.ItemName);
  98. row.ConstantColumn(50).AlignRight().Text(orderItem.Count);
  99. row.ConstantColumn(50).AlignRight().Text($"{orderItem.Price}$");
  100. row.ConstantColumn(50).AlignRight().Text($"{orderItem.Count*orderItem.Price}$");
  101. });
  102. });
  103. var elementHeight = element.Size.Height;
  104. if (totalHeight + elementHeight > context.AvailableSize.Height)
  105. break;
  106. totalHeight += elementHeight;
  107. yield return (orderItem, element);
  108. }
  109. }
  110. }
  111. public static class DynamicExamples
  112. {
  113. [Test]
  114. public static void Dynamic()
  115. {
  116. RenderingTest
  117. .Create()
  118. .PageSize(PageSizes.A5)
  119. .FileName()
  120. .ShowResults()
  121. .Render(container =>
  122. {
  123. var items = Enumerable.Range(0, 25).Select(x => new OrderItem()).ToList();
  124. container
  125. .Background(Colors.White)
  126. .Padding(25)
  127. .Decoration(decoration =>
  128. {
  129. decoration
  130. .Header()
  131. .PaddingBottom(5)
  132. .Text(text =>
  133. {
  134. text.DefaultTextStyle(TextStyle.Default.SemiBold().Color(Colors.Blue.Darken2).Size(16));
  135. text.Span("Page ");
  136. text.CurrentPageNumber();
  137. text.Span(" of ");
  138. text.TotalPages();
  139. });
  140. decoration
  141. .Content()
  142. .Dynamic(new OrdersTable(items));
  143. });
  144. });
  145. }
  146. }
  147. }