How to: Combine Links via the CompositeLink

  • 6 minutes to read

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.

    // Create the report and show the preview window.

// 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;

// 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;

// 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;

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.


A complete sample project is available in the DevExpress Code Examples database at

See Also