windowsforms-174-controls-and-libraries-printing-exporting-examples-using-printing-links-how-to-combine-links-via-the-compositelink.md
This topic addresses the question of whether, and how, a complex windows form, comprised of different controls, can be printed in a custom manner.
The XtraPrinting Library enables you to print out multiple components within a single report. To accomplish this a CompositeLink class is used. It enables you to combine several printing links in the desired order. Each printing link represents a report, so the composite link can actually be a nested report. Since each component which implements the IPrintable interface can be printed via the PrintableComponentLink instance, reports of high complexity can be easily created.
Let’s illustrate it with a simple example. Suppose we have a windows form with two Data Grid controls. A printout should look as follows: a custom header, the first grid, empty space (a gap, page wide), a custom header for the second grid, the second grid. A timestamp in the upper margin is necessary.
We can represent each element (grid, header, empty space) with a printing link. Then we should combine them into one composite link and draw the PageInfoBrick in the MarginalHeader area of the page.
This example demonstrates how to combine reports in code. It uses event handlers to create detail areas of combined reports.
In a real task, you can use event handlers to create any area of a report, enclosed within the composite report, except for marginal headers and footers, which belong solely to the composite report itself (for areas definition, see Document Sections).
using System;
using System.Drawing;
using System.Windows.Forms;
using DevExpress.XtraPrinting;
using DevExpress.XtraPrintingLinks;
// ...
private void simpleButton1_Click(object sender, EventArgs e) {
// Create objects and define event handlers.
CompositeLink composLink = new CompositeLink(new PrintingSystem());
composLink.CreateMarginalHeaderArea +=
new CreateAreaEventHandler(composLink_CreateMarginalHeaderArea);
PrintableComponentLink pcLink1 = new PrintableComponentLink();
PrintableComponentLink pcLink2 = new PrintableComponentLink();
Link linkMainReport = new Link();
linkMainReport.CreateDetailArea +=
new CreateAreaEventHandler(linkMainReport_CreateDetailArea);
Link linkGrid1Report = new Link();
linkGrid1Report.CreateDetailArea +=
new CreateAreaEventHandler(linkGrid1Report_CreateDetailArea);
Link linkGrid2Report = new Link();
linkGrid2Report.CreateDetailArea +=
new CreateAreaEventHandler(linkGrid2Report_CreateDetailArea);
// Assign the controls to the printing links.
pcLink1.Component = this.gridControl1;
pcLink2.Component = this.gridControl2;
// Populate the collection of links in the composite link.
// The order of operations corresponds to the document structure.
composLink.Links.Add(linkGrid1Report);
composLink.Links.Add(pcLink1);
composLink.Links.Add(linkMainReport);
composLink.Links.Add(linkGrid2Report);
composLink.Links.Add(pcLink2);
// Create the report and show the preview window.
composLink.ShowPreviewDialog();
}
// Inserts a PageInfoBrick into the top margin to display the time.
void composLink_CreateMarginalHeaderArea(object sender, CreateAreaEventArgs e) {
e.Graph.DrawPageInfo(PageInfo.DateTime, "{0:hhhh:mmmm:ssss}", Color.Black,
new RectangleF(0, 0, 200, 50), BorderSide.None);
}
// Creates a text header for the first grid.
void linkGrid1Report_CreateDetailArea(object sender, CreateAreaEventArgs e) {
TextBrick tb = new TextBrick();
tb.Text = "Northwind Traders";
tb.Font = new Font("Arial", 15);
tb.Rect = new RectangleF(0, 0, 300, 25);
tb.BorderWidth = 0;
tb.BackColor = Color.Transparent;
tb.HorzAlignment = DevExpress.Utils.HorzAlignment.Near;
e.Graph.DrawBrick(tb);
}
// Creates an interval between the grids and fills it with color.
void linkMainReport_CreateDetailArea(object sender, CreateAreaEventArgs e) {
TextBrick tb = new TextBrick();
tb.Rect = new RectangleF(0, 0, e.Graph.ClientPageSize.Width, 50);
tb.BackColor = Color.Gray;
e.Graph.DrawBrick(tb);
}
// Creates a text header for the second grid.
void linkGrid2Report_CreateDetailArea(object sender, CreateAreaEventArgs e) {
TextBrick tb = new TextBrick();
tb.Text = "Suppliers";
tb.Font = new Font("Arial", 15);
tb.Rect = new RectangleF(0, 0, 300, 25);
tb.BorderWidth = 0;
tb.BackColor = Color.Transparent;
tb.HorzAlignment = DevExpress.Utils.HorzAlignment.Near;
e.Graph.DrawBrick(tb);
}
Imports System
Imports System.Drawing
Imports System.Windows.Forms
Imports DevExpress.XtraPrinting
Imports DevExpress.XtraPrintingLinks
' ...
Private Sub simpleButton1_Click(ByVal sender As Object, _
ByVal e As EventArgs) Handles simpleButton1.Click
' Create objects and define event handlers.
Dim composLink As CompositeLink = New CompositeLink(New PrintingSystem())
AddHandler composLink.CreateMarginalHeaderArea, AddressOf composLink_CreateMarginalHeaderArea
Dim pcLink1 As PrintableComponentLink = New PrintableComponentLink()
Dim pcLink2 As PrintableComponentLink = New PrintableComponentLink()
Dim linkMainReport As Link = New Link()
AddHandler linkMainReport.CreateDetailArea, AddressOf linkMainReport_CreateDetailArea
Dim linkGrid1Report As Link = New Link()
AddHandler linkGrid1Report.CreateDetailArea, AddressOf linkGrid1Report_CreateDetailArea
Dim linkGrid2Report As Link = New Link()
AddHandler linkGrid2Report.CreateDetailArea, AddressOf linkGrid2Report_CreateDetailArea
' Assign the controls to the printing links.
pcLink1.Component = Me.gridControl1
pcLink2.Component = Me.gridControl2
' Populate the collection of links in the composite link.
' The order of operations corresponds to the document structure.
composLink.Links.Add(linkGrid1Report)
composLink.Links.Add(pcLink1)
composLink.Links.Add(linkMainReport)
composLink.Links.Add(linkGrid2Report)
composLink.Links.Add(pcLink2)
' Create the report and show the preview window.
composLink.ShowPreviewDialog()
End Sub
' Inserts a PageInfoBrick into the top margin to display the time.
Private Sub composLink_CreateMarginalHeaderArea(ByVal sender As Object, _
ByVal e As CreateAreaEventArgs)
e.Graph.DrawPageInfo(PageInfo.DateTime, "{0:hhhh:mmmm:ssss}", _
Color.Black, New RectangleF(0, 0, 200, 50), BorderSide.None)
End Sub
' Creates a text header for the first grid.
Private Sub linkGrid1Report_CreateDetailArea(ByVal sender As Object, _
ByVal e As CreateAreaEventArgs)
Dim tb As TextBrick = New TextBrick()
tb.Text = "Northwind Traders"
tb.Font = New Font("Arial", 15)
tb.Rect = New RectangleF(0, 0, 300, 25)
tb.BorderWidth = 0
tb.BackColor = Color.Transparent
tb.HorzAlignment = DevExpress.Utils.HorzAlignment.Near
e.Graph.DrawBrick(tb)
End Sub
' Creates an interval between the grids and fills it with color.
Private Sub linkMainReport_CreateDetailArea(ByVal sender As Object, _
ByVal e As CreateAreaEventArgs)
Dim tb As TextBrick = New TextBrick()
tb.Rect = New RectangleF(0, 0, e.Graph.ClientPageSize.Width, 50)
tb.BackColor = Color.Gray
e.Graph.DrawBrick(tb)
End Sub
' Creates a text header for the second grid.
Private Sub linkGrid2Report_CreateDetailArea(ByVal sender As Object, _
ByVal e As CreateAreaEventArgs)
Dim tb As TextBrick = New TextBrick()
tb.Text = "Suppliers"
tb.Font = New Font("Arial", 15)
tb.Rect = New RectangleF(0, 0, 300, 25)
tb.BorderWidth = 0
tb.BackColor = Color.Transparent
tb.HorzAlignment = DevExpress.Utils.HorzAlignment.Near
e.Graph.DrawBrick(tb)
End Sub
Note
You can create any areas within the enclosed reports, except marginal, so the LinkBase.CreateMarginalHeaderArea and LinkBase.CreateMarginalFooterArea events cannot be used.
The reports inserted within a report are also called “subreports”. Subreports are automatically generated when you call the Link.CreateDocument method for the CompositeLink, or invoke the preview window using the Link.ShowPreviewDialog method.
Although the composite link technique, described earlier, is highly recommended, there are other ways to create subreports:
To insert a report generated by a specific link into another report, you can use the PrintableComponentLinkBase.AddSubreport method. This method must be called only when a report is being generated, not after. You can insert a subreport via the PrintableComponentLinkBase.AddSubreport method at any position between the PrintingSystemBase.Begin and PrintingSystemBase.End method invocations.
A subreport is inserted into the main report at the position where the xref:PrintableComponentLinkBase PrintableComponentLinkBase.AddSubreport method is called. The method also invokes the sequence of report area creation events. Only the LinkBase.CreateMarginalHeaderArea and LinkBase.CreateMarginalFooterArea events are not used in this sequence for a subreport. The printing system uses the first report page header or footer instead of the current report page header or footer.
You can also create subreports manually via a PrintingSystem object. The PrintingSystemBase.BeginSubreport and PrintingSystemBase.EndSubreport methods inform the printing system that a subreport should be inserted at a specific location.
See Also