Skip to main content
.NET 8.0+

How to: Merge the Pages of Two Reports

  • 3 minutes to read

This example demonstrates how to modify report content before it is displayed. For information on how to add a separate report to the end of another report, refer to the Add a Report to the End/Beginning topic. In this topic, it is assumed that you have an XAF application that uses the Reports V2 Module, and you have created one or more reports (see Reports V2 Module Overview).

In .NET Applications

Assume that you have two reports (called First Report and Second Report) in your application. To merge these two reports right before they are displayed, implement the following helper class, which handles the First Report‘s AfterPrint event. In the event handler, use the IReportDataSourceHelper service to generate the Second Report document. Handle the First Report‘s ModifyDocument event to append the generated Second Report document’s contents to the First Report. In this example, pages from the Second Report will be appended to the pages of the First Report when the First Report is previewed.

using System;
using DevExpress.XtraReports.UI;
using DevExpress.ExpressApp;
using DevExpress.ExpressApp.ReportsV2;
// ...
public class MergeReportHelper {
    public static void MergeReportsBeforeShow(ReportLoadedContext context) {
        if (context.Report is XtraReport && context.Report.DisplayName == "First Report") {
            context.Report.AfterPrint += (sender, e) => {
                XtraReport firstReport = sender as XtraReport;

                var objectSpaceFactory = context.ServiceProvider.GetRequiredService<IObjectSpaceFactory>();
                using var objectSpace = objectSpaceFactory.CreateObjectSpace(typeof(ReportDataV2));
                IReportDataV2 reportData = objectSpace.FirstOrDefault<ReportDataV2>(data => data.DisplayName == "Second Report");
                if (reportData != null) {
                    var secondReport = context.ServiceProvider.GetRequiredService<IReportStorage>().LoadReport(reportData);
                    var dataSourceHelper = context.ServiceProvider.GetRequiredService<IReportDataSourceHelper>();
                    dataSourceHelper.SetupReport(secondReport);
                    secondReport.CreateDocument(false);
                    firstReport.ModifyDocument(x => x.AddPages(secondReport.Pages));
                    firstReport.PrintingSystem.ContinuousPageNumbering = true;
                }
            };
        }
    }
}

The IReportDataSourceHelper.SetupReport method call is required to display a report in XAF. Without it, the data source will not supply data.

In the application’s Startup.cs file, add the OnReportLoaded event handler to the builder.Modules.AddReports method call. In this event handler, call the MergeReportHelper.MergeReportsBeforeShow static method as shown below:

File: MySolution.Blazor.Server/Startup.cs, MySolution.Win/Startup.cs, MySolution.WebApi/Startup.cs

// ...
builder.Modules
    .AddReports(options => {
        // ...
        options.Events.OnReportLoaded = context => {
            MergeReportHelper.MergeReportsBeforeShow(context);
        };
    })
// ...

In .NET Framework Applications

To merge two reports right before they are displayed, implement the following helper class, which handles the ReportDataSourceHelper.BeforeShowPreview event. In this example, pages from the SecondReport will be appended to the pages of the FirstReport when the FirstReport is previewed.

using System;
using DevExpress.XtraReports.UI;
using DevExpress.ExpressApp;
using DevExpress.ExpressApp.ReportsV2;
// ...
public class MergeReportHelper {
    ReportDataSourceHelper helper;
    public MergeReportHelper(ModuleList modules) {
        ReportsModuleV2 module = ReportsModuleV2.FindReportsModule(modules);
        if (module != null) {
            module.ReportsDataSourceHelper.BeforeShowPreview +=
                ReportsDataSourceHelper_BeforeShowPreview;
        }
    }
    private void ReportsDataSourceHelper_BeforeShowPreview(
        object sender, BeforeShowPreviewEventArgs e) {
        MergeReportsBeforeShow(e.Report, (ReportDataSourceHelper)sender);
    }
    private void MergeReportsBeforeShow(
        XtraReport report, ReportDataSourceHelper reportsDataSourceHelper) {
        if (report is FirstReport) {
            report.AfterPrint += report_AfterPrint;
            helper = reportsDataSourceHelper;
        }
    }
    void report_AfterPrint(object sender, EventArgs e) {
        FirstReport firstReport = sender as FirstReport;
        SecondReport secondReport = new SecondReport();
        helper.SetupReport(secondReport);
        secondReport.CreateDocument(false);
        firstReport.ModifyDocument(x => x.AddPages(secondReport.Pages));
        firstReport.PrintingSystem.ContinuousPageNumbering = true;
    }
}

The ReportDataSourceHelper.SetupReport method call is required to display a report in XAF. Without it, the data source will not provide data.

Create an instance of the MergeReportHelper class after the application setup is complete. You can do it in the platform-agnostic module by handling the XafApplication.SetupComplete event in the overridden ModuleBase.Setup method.

File: MySolution.Module/Module.cs

public override void Setup(XafApplication application) {
    base.Setup(application);
    application.SetupComplete += delegate(object sender, EventArgs e) {
        new MergeReportHelper(((XafApplication)sender).Modules);
    };
}