I have an MDI application with many different Forms. Then I have a ReportViewer control inside a ReportForm where I dynamically load RDLC reports.
The ReportForm is opened from the other Forms with a button click.
Inside the ReportForm, above the ReportViewer control, there's a ComboBox with a list of available reports for that specific Form. That list is dynamically generated based on the Form from which the ReportViewer was opened.
The list is generated by looking for a Form associated folder, inside the Reports Project (which output is a DLL), that contains the corresponding .rdlc files.
The question is this:
Since the RDLC are all already generated and configured with Report Designer and binded to specific DataSet and DataTable, why do I need to recreate everytime the ReportDataSource object (DataSet, DataTable) and rebind it to the report?
My actual code:
// Code used to open a new ReportForm Window
private void bindingNavigatorViewReport_Click(object sender, EventArgs e)
{
// If the form is already open, then Focus on it
if (MdiMain.IsFormOpen(ApplicationForm.ReportForm))
{
Application.OpenForms[formName].Focus();
}
// I need to instantiate a new ReportForm
else
{
/* The parameters are:
* - ApplicationForm enum which identifies the Form;
* - The Form corresponding DataSet
*/
ReportForm reportForm = new ReportForm(ApplicationForm.SchoolForm, SchoolDataSet)
{
MdiParent = MdiParent,
Icon = Resources.ViewReportIcon
};
reportForm.Show();
}
}
// Code used to load report
/* In the ReportForm class I have a method that casts the parameters to the
* specific types. So I can obtain the DataSet to use.
*/
// Report Path inside DLL assembly taken from SelectedValue of ComboBox
string reportSource = cmbReport.SelectedValue.ToString();
// Get report Stream from DLL Path
Stream reportStream = assembly.GetManifestResourceStream(reportSource);
// Load report Stream
reportViewer1.LocalReport.LoadReportDefinition(reportStream);
/* Create a new DataSource with DataSet name and DataTable object
* The DataTable object must come from DataSet, ie: DataSet.SchoolListDataTable.
*/
ReportDataSource rds = new ReportDataSource("DataSetName", DataTableObject);
reportViewer1.LocalReport.DataSources.Clear();
reportViewer1.LocalReport.DataSources.Add(rds);
reportViewer1.LocalReport.Refresh();
The main problem is that I have no "dynamic way" to get from the Forms the DataTable object for every report associated to the Form, since when I click on the "Open report window" button, I have a list of reports and so on DataSet (associated to that Form) but many different DataTables, not just one.
** UPDATE: Final solution **
Finally I found that when I load the report stream I can use this code:
// Loads all the data sources associated to the current selected report
IEnumerable<string> dsNames = reportViewer1.LocalReport.GetDataSourceNames();
foreach (string dsName in dsNames)
{
// dsName is equal to the string "V_REP_SCHOOLS" that is the corresponding DataTable name
ReportDataSource rds = new ReportDataSource(dsName, _currentReportDataSet.Tables[dsName]);
reportViewer1.LocalReport.DataSources.Add(rds);
}
After loading the report stream (look at the code above), the GetDataSourceNames() method gives me all the DataSource (in effect DataSet if you look on the Report Data panel in the report designer) that is named inside the report.
So I named my DataSet as the DataTable from which I need to load my data, such as "V_REPORT_SCHOOLS", and then I loaded the DataTable by name from my DataSet.
DataSetis the same for each report of a specific Form, but theDataTablesare different. So when I call the ReportForm I can pass theDataSetclass (XSD schema) as a parameter but not the specificDataTable, because there're many. I need that. Please take a look again at the question for the code update. - Cheshire Cat