Looks like FixedDocument
is the way to go to have multi-paged formatted document with rolling page subtotal. Since I'm still in the process of figuring out how to add page subtotal all my code is in one function print
. Here're the steps:
- get the
Size
of the FixeedDocument/Page
and set uniform margins.
- add header
- add footer
- determine the Content Area of the Fixed page by subtracting top/bottom margins and heights of header/footer from page
Size
- instantiate
ListBox
for content items and put that in the Grid
for content area
- add 2 content item and check the height of the content
ListBox
- set position of the header, content area and footer in the
Grid
for the FixedPage
, set row heights of the Grid
accordingly and put all those in the Grid
- create
FixedDocument
, FixedPage
and print.
this unnecessary line's been added to format code
void print(object o)
{
var dialog = new PrintDialog();
if (dialog.ShowDialog() == true)
{
var size = new Size(dialog.PrintableAreaWidth, dialog.PrintableAreaHeight);
var margin = 96d;
var header = new Grid()
{
Width = size.Width - 2 * margin,
Children =
{
new ReportHeader() /*subclass of Control*/
{
Title = "My Title",
SubTitle = "My Sub Title",
Date = $" as at {DateTime.Today.AddDays(5).ToString("dd MMMM, yyyy")}"
}
}
};
header.Measure(size);
header.Arrange(new Rect(header.DesiredSize));
var footer = new Grid() { Children = { new ReportFooter() /*subclass of Control*/ } };
footer.Measure(size);
footer.Arrange(new Rect(footer.DesiredSize));
var contentHeight = size.Height - (2 * margin) - header.DesiredSize.Height - footer.DesiredSize.Height;
var content = new ReportItems(); //subclass of ListBox
var contentArea = new Grid()
{
Height = contentHeight,
Children = { content }
};
contentArea.Measure(new Size(size.Width, contentHeight));
contentArea.Arrange(new Rect(contentArea.DesiredSize));
content.Items.Add(new Item()
{
Date = DateTime.Today,
Particulars = "Some text",
Receivable = 10000,
Receipt = 0,
Balance = 10000
});
content.Measure(size);
content.Arrange(new Rect(content.DesiredSize));
Debug.WriteLine($"Content Height : {content.DesiredSize.Height}");
content.Items.Add(new Item()
{
Date = DateTime.Today,
Particulars = "Some other text",
Receivable = 0,
Receipt = 5000,
Balance = 5000
});
content.Measure(size);
content.Arrange(new Rect(content.DesiredSize));
Debug.WriteLine($"Content Height : {content.DesiredSize.Height}");
Grid.SetRow(header, 0);
Grid.SetRow(contentArea, 1);
Grid.SetRow(footer, 2);
var pageVisual = new Grid()
{
RowDefinitions =
{
new RowDefinition(){Height = new GridLength(header.DesiredSize.Height)},
new RowDefinition(){Height = new GridLength(contentArea.DesiredSize.Height)},
new RowDefinition(){Height = new GridLength(footer.DesiredSize.Height)}
},
Children = { header, contentArea, footer }
};
var doc = new FixedDocument();
doc.DocumentPaginator.PageSize = size;
var page = new FixedPage()
{
Height = size.Height,
Width = size.Width,
Margin = new Thickness(96),
Children = { pageVisual }
};
doc.Pages.Add(new PageContent() { Child = page });
dialog.PrintDocument(doc.DocumentPaginator, "");
}
}
I've 2 issues, first, header and footers are custom control and subclass of Control
, If I add those directly in the pageVisual
grid, those don't appear in the document! So I've put both of those in Grid to see them in my document. What to do to be able to add them directly in the page Grid?
and second, after adding each item in the ListBox
, content, I called Measure
and Arrange
on content and here's the output:
Content Height : 17.96
Content Height : 17.96
Why the height doesn't grow as I add item in the ListBox
? How can I get the actual height of the ListBox
after adding an Item?
EDIT
Here's the output:
Title, Sub Title, Date and Table Header are part of Header
custom control. Line and two pieces of Text are part of Foother
custom control.