-
Notifications
You must be signed in to change notification settings - Fork 204
Subreports
A sub-report embeds one report inside another. The outer (parent) report defines the layout and data; the inner (child) report is a separate .rdl file that the engine loads and renders inline.
- Open the parent report in the designer.
- From the toolbox, drag a Subreport item onto the report body.
- Right-click the sub-report item and choose Properties.
- In the Report Name field, enter the path to the child
.rdlfile — either an absolute path or a path relative to the parent report's folder. - Optionally map parameters from the parent report to the child using the Parameters tab.
The engine resolves the child .rdl path relative to the Folder property set on RDLParser. Always set Folder when parsing a report that contains sub-reports.
var rdlp = new RDLParser(await System.IO.File.ReadAllTextAsync(rdlPath))
{
Folder = Path.GetDirectoryName(rdlPath)
};
using var report = await rdlp.Parse();When the child report uses a live database query, no extra code is needed — the engine runs the child's query automatically.
When the child report's dataset should be populated from a DataTable (instead of a database query), subscribe to the SubreportDataRetrieval event on the parent Report before calling RunGetData. The event fires once per sub-report instance, passing a SubreportDataRetrievalEventArgs whose Report property is the child report.
using Majorsilence.Reporting.Rdl;
RdlEngineConfig.RdlEngineConfigInit();
var rdlp = new RDLParser(await System.IO.File.ReadAllTextAsync(rdlPath))
{
Folder = Path.GetDirectoryName(rdlPath)
};
using var report = await rdlp.Parse();
// Subscribe before RunGetData
report.SubreportDataRetrieval += (sender, e) =>
{
// e.Report is the child Report instance
// Supply data to the child's DataSet
var childDataTable = GetChildData(); // your method
e.Report.DataSets["ChildDataSetName"].SetData(childDataTable);
};
await report.RunGetData(null);
using var ms = new MemoryStreamGen();
await report.RunRender(ms, OutputPresentationType.PDF);
var pdf = ((System.IO.MemoryStream)ms.GetStream()).ToArray();The Avalonia and WinForms viewers expose the same event via their own surface so you can wire it up without accessing the Report object directly.
ReportViewer.SubreportDataRetrieval += (sender, e) =>
{
e.Report.DataSets["ChildDataSetName"].SetData(GetChildData());
};
await ReportViewer.SetSourceFileAsync(new Uri(rdlPath));// Wire up after SetSourceFile, before Rebuild
var rpt = await rdlView.Report();
rpt.SubreportDataRetrieval += (sender, e) =>
{
e.Report.DataSets["ChildDataSetName"].SetData(GetChildData());
};
await rdlView.Rebuild();To override the connection string in the child report as well as the parent, set OverwriteInSubreport = true on RDLParser:
var rdlp = new RDLParser(rdlSource)
{
Folder = Path.GetDirectoryName(rdlPath),
OverwriteConnectionString = "Server=prod;Database=mydb;Integrated Security=true",
OverwriteInSubreport = true
};