I would like to stick with one single form and ReportViewer
control, and at runtime assign various reports and data sources. The diverse and complex solutions to this revealed by a quick google check prompted me to rather ask here. How can I achieve this?
You'll need a form featuring a ReportViewer control, RDLC reports, and data sources; there are possibly several ways of implementing this, but you can have a "report manager" class exposing methods that each display a specific report (ex. ShowOrdersReport()
, ShowTimeSheetReport()
, etc.) - or you could define a base ReportBase
class with a Show()
method implementation that prompts for parameters when needed... whatever works, it will essentially boil down to this:
var reportForm = new ReportViewerForm(); // instantiate the form
// load the report definition into the viewer:
reportForm.reportViewer1.LocalReport.ReportEmbeddedResource = "Namespace.Report.rdlc";
// loading the data works great with a DataSet:
var data = _reportingDataSet.Tables[0];
// create the ReportDataSource with the report data:
var reportDataSource = new ReportDataSource("rdsReportDataSource", data);
reportForm.ShowReport(new[] { reportDataSource });
Here you'll want to inject the _reportingDataSet
dependency; if you're using parameterized stored procedures, you'll want to prompt for the report parameters before you populate the DataSet.
The ShowReport()
method adds the data sources to LocalReport.DataSources
, and then calls RefreshReport()
which displays the report you've specified.
public void ShowReport(IEnumerable<ReportDataSource> dataSources)
{
foreach (var dataSource in dataSources)
reportViewer1.LocalReport.DataSources.Add(dataSource);
reportViewer1.RefreshReport();
}