I've been following this example to add header and footer in my DocumentPage and it looks like in this fuction I can add header and footer:
public override DocumentPage GetPage(int pageNumber)
{
var oldPage = paginator.GetPage(pageNumber);
var visual = new ContainerVisual();
var face = new Typeface("Times New Roman");
var header = new DrawingVisual();
var footer = new DrawingVisual();
using (var dc = header.RenderOpen())
dc.DrawText(new FormattedText("Header", CultureInfo.CurrentCulture, FlowDirection.LeftToRight, face, 14, Brushes.Black), new Point(0, 0));
using (var dc = footer.RenderOpen())
dc.DrawText(new FormattedText("Page " + (pageNumber + 1).ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, face, 14, Brushes.Black), new Point(720, 1023));
visual.Children.Add(header);
visual.Children.Add(oldPage.Visual);
visual.Children.Add(footer);
return new DocumentPage(visual);
}
for the header part I don't want that DrawingVisual
. I want to add the following parts, a Paragraph
and 2 Table
, of my FlowDocument
as the header for all pages:
var fd = new FlowDocument();
fd.PageWidth = 816;
fd.PageHeight = 1123.2;
fd.PagePadding = new Thickness(96);
var para = new Paragraph(new Run("Trade Report"));
para.TextAlignment = TextAlignment.Center;
para.FontWeight = FontWeights.Bold;
para.FontSize = 24;
fd.Blocks.Add(para);
var table1 = new Table();
table1.Margin = new Thickness(0, 24, 0, 24);
var rowGroup1 = new TableRowGroup();
rowGroup1.FontWeight = FontWeights.Bold;
var row1 = new TableRow();
var codeCell = new TableCell(new Paragraph(new Run("Customer Code: " + CustomerCode)));
codeCell.TextAlignment = TextAlignment.Left;
row1.Cells.Add(codeCell);
var dateCell = new TableCell(new Paragraph(new Run("Date: " + DateTime.Now.ToShortDateString())));
dateCell.TextAlignment = TextAlignment.Right;
row1.Cells.Add(dateCell);
rowGroup1.Rows.Add(row1);
table1.RowGroups.Add(rowGroup1);
fd.Blocks.Add(table1);
var table2 = new Table();
table2.CellSpacing = 0;
var rowGroup2 = new TableRowGroup();
rowGroup2.FontWeight = FontWeights.Bold;
var row2 = new TableRow();
row2.Background = new SolidColorBrush(Colors.LightGray);
foreach (var head in headers)
{
var cell = new TableCell(new Paragraph(new Run(head)));
if (head == "Quantity" || head == "Price" || head == "Value") cell.TextAlignment = TextAlignment.Right;
else cell.TextAlignment = TextAlignment.Center;
cell.BorderBrush = new SolidColorBrush(Colors.Black);
cell.BorderThickness = new Thickness(0, 1, 0, 1);
row2.Cells.Add(cell);
}
rowGroup2.Rows.Add(row2);
table2.RowGroups.Add(rowGroup2);
fd.Blocks.Add(table2);
How to do that?
EDIT
Feels like something similar to these:
var t1 = new TextBlock() { Text = "Some Text 1", FontWeight = FontWeights.Bold };
var t2 = new TextBlock() { Text = "Some Text 2", FontWeight = FontWeights.SemiBold };
var t3 = new TextBlock() { Text = "Some Text 3"};
var t4 = new TextBlock() { Text = "Some Text 4"};
var canvas = new Grid() { Width = oldPage.Size.Width};
canvas.ColumnDefinitions.Add(new ColumnDefinition());
canvas.ColumnDefinitions.Add(new ColumnDefinition());
canvas.ColumnDefinitions.Add(new ColumnDefinition());
canvas.ColumnDefinitions.Add(new ColumnDefinition());
Grid.SetColumn(t1, 0);
Grid.SetColumn(t2, 1);
Grid.SetColumn(t3, 2);
Grid.SetColumn(t4, 3);
canvas.Children.Add(t1);
canvas.Children.Add(t2);
canvas.Children.Add(t3);
canvas.Children.Add(t4);
canvas.Measure(new Size(oldPage.Size.Width, oldPage.Size.Height));
canvas.Arrange(new Rect(canvas.DesiredSize));
var size = new Size() { Height = canvas.ActualHeight, Width = canvas.ActualWidth };
using (var dc = header.RenderOpen())
{
var brush = new VisualBrush(canvas);
dc.DrawRectangle(brush, null, new Rect(size));
}
visual.Children.Add(header);
is the best solution for printing and it appears that I can add anything (StackPanel, DockPanel, Canvas, ViewBox etc.) to DocumentPage
with VisualBrush
, not bad!
is there anything better?
So to solve the problem I've extended the DocumentPaginator
in this way:
public class FlowPaginator : DocumentPaginator
{
string[] headers = { "Trans No.", "Order No.", "Type", "Price", "Quantity", "Value" };
int code;
DocumentPaginator paginator;
public FlowPaginator(FlowDocument doc, int customerCode)
{
code = customerCode;
paginator = ((IDocumentPaginatorSource)doc).DocumentPaginator;
}
public override bool IsPageCountValid => paginator.IsPageCountValid;
public override int PageCount => paginator.PageCount;
public override Size PageSize { get => paginator.PageSize; set => paginator.PageSize = value; }
public override IDocumentPaginatorSource Source => paginator.Source;
public override DocumentPage GetPage(int pageNumber)
{
var oldPage = paginator.GetPage(pageNumber);
var visual = new ContainerVisual();
var header = new DrawingVisual();
var footer = new DrawingVisual();
#region Heading
var heading = new Grid() { Width = oldPage.Size.Width - 2 * 96 };
heading.RowDefinitions.Add(new RowDefinition());
heading.RowDefinitions.Add(new RowDefinition());
heading.ColumnDefinitions.Add(new ColumnDefinition());
heading.ColumnDefinitions.Add(new ColumnDefinition());
var t1 = new TextBlock() { Text = "Trade Report", FontSize = 24, FontWeight = FontWeights.Bold, HorizontalAlignment = HorizontalAlignment.Center };
var t2 = new TextBlock() { Text = "Customer Code: " + code, FontWeight = FontWeights.SemiBold, HorizontalAlignment = HorizontalAlignment.Left };
var t3 = new TextBlock() { Text = "Date: " + DateTime.Now.ToShortDateString(), FontWeight = FontWeights.SemiBold, HorizontalAlignment = HorizontalAlignment.Right };
Grid.SetColumn(t1, 0); Grid.SetRow(t1, 0); Grid.SetColumnSpan(t1, 2);
Grid.SetColumn(t2, 0); Grid.SetRow(t2, 1);
Grid.SetColumn(t3, 1); Grid.SetRow(t3, 1);
heading.Children.Add(t1);
heading.Children.Add(t2);
heading.Children.Add(t3);
heading.Measure(new Size(oldPage.Size.Width, oldPage.Size.Height));
heading.Arrange(new Rect(heading.DesiredSize));
var headingSize = new Size() { Height = heading.ActualHeight, Width = heading.ActualWidth };
#endregion
#region TableHeader
var tableHeader = new Grid() { Width = oldPage.Size.Width - 2 * 96 };
var border = new Border()
{
Background = new SolidColorBrush(Colors.LightGray),
BorderBrush = new SolidColorBrush(Colors.Black),
BorderThickness = new Thickness(0, 1, 0, 1),
Child = tableHeader
};
for (int i = 0; i < headers.Length; i++)
{
tableHeader.ColumnDefinitions.Add(new ColumnDefinition());
var head = new TextBlock() { Text = headers[i], FontWeight = FontWeights.Bold };
if(i > 2)
{
tableHeader.ColumnDefinitions[i].Width = new GridLength(138);
head.HorizontalAlignment = HorizontalAlignment.Right;
}
else
{
tableHeader.ColumnDefinitions[i].Width = new GridLength(70);
head.HorizontalAlignment = HorizontalAlignment.Center;
}
Grid.SetColumn(head, i);
tableHeader.Children.Add(head);
}
border.Measure(new Size(oldPage.Size.Width, oldPage.Size.Height));
border.Arrange(new Rect(border.DesiredSize));
var borderSize = new Size() { Height = border.ActualHeight, Width = border.ActualWidth };
#endregion
using (var dc = header.RenderOpen())
{
dc.DrawRectangle(new VisualBrush(heading), null, new Rect(new Point(96, 96), headingSize));
dc.DrawRectangle(new VisualBrush(border), null, new Rect(new Point(96, 96 * 1.55), borderSize));
}
using(var dc = footer.RenderOpen())
{
var text = new TextBlock() { Text = "Page: " + (pageNumber + 1) };
text.Measure(new Size(oldPage.Size.Width, oldPage.Size.Height));
text.Arrange(new Rect(text.DesiredSize));
var texSize = new Size() { Height = text.ActualHeight, Width = text.ActualWidth };
dc.DrawRectangle(new VisualBrush(text), null, new Rect(oldPage.Size.Width - 96, oldPage.Size.Height - 96, texSize.Width, texSize.Height));
}
visual.Children.Add(header);
visual.Children.Add(oldPage.Visual);
visual.Children.Add(footer);
return new DocumentPage(visual);
}
}
it repeats the header and creates footer and in my PrintDoc
function I only generate rows and set background for every other row from my List
:
void PrintDoc(object obj)
{
doc = new FlowDocument();
doc.PageWidth = 96 * 8.5;
doc.PageHeight = 96 * 11.7;
doc.PagePadding = new Thickness(96, 96 * 1.7, 96, 96 * 1.1);
var table = new Table();
table.CellSpacing = 0;
for (int i = 0; i < 6; i++)
{
var column = new TableColumn();
if (i < 3) column.Width = new GridLength(70);
else column.Width = new GridLength(138);
table.Columns.Add(column);
}
var rowNum = 1;
foreach (var item in Trade)
{
var rowGroup = new TableRowGroup();
var row = new TableRow();
row.Cells.Add(new TableCell(new Paragraph(new Run(item.TransNo.ToString()))) { TextAlignment = TextAlignment.Center});
row.Cells.Add(new TableCell(new Paragraph(new Run(item.OrderNo.ToString()))) { TextAlignment = TextAlignment.Center});
row.Cells.Add(new TableCell(new Paragraph(new Run(item.Type))) { TextAlignment = TextAlignment.Center});
row.Cells.Add(new TableCell(new Paragraph(new Run(item.Price.ToString("N2")))) { TextAlignment = TextAlignment.Right});
row.Cells.Add(new TableCell(new Paragraph(new Run(item.Quantity.ToString("N0")))) { TextAlignment = TextAlignment.Right});
row.Cells.Add(new TableCell(new Paragraph(new Run(item.ValueTraded.ToString("N2")))) { TextAlignment = TextAlignment.Right});
if (rowNum % 2 == 0) row.Background = new SolidColorBrush(Colors.LightGray);
rowGroup.Rows.Add(row);
table.RowGroups.Add(rowGroup);
rowNum++;
}
doc.Blocks.Add(table);
PrintDialog dialog = new PrintDialog();
dialog.CurrentPageEnabled = true;
dialog.UserPageRangeEnabled = true;
if (dialog.ShowDialog() == true)
{
var paginator = new FlowPaginator(doc, CustomerCode);
dialog.PrintDocument(paginator, "");
}
}
Much simpler than what I'd thought, beautiful!
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.