1

Following on from an earlier question about dynamic columns in a report viewer, I thought I would at least attempt to get things working.
The output being displayed are columns of mathematical factors, each with their own unique name. These factors (any number from 1 to 10 can be selected) display without issue in my DataGridView control - I generate a DataTable by adding rows/columns as required, and then set the datatable as the Datasource for the DataGridView.
I have added a ReportViewer to my WinForm, and generated a RDLC file. Rather than spend hours trying to figure out how to make it dynamic, my RDLC is set up with 10 columns (as I know there will never be more than this), and the DataSet is assigned to my ReportViewer control. I then use the following code to assign the data to the viewer:

DataTable dt = new DataTable();
var source = this.dgvSelectedElements.DataSource;
while (source is BindingSource)
{
    source = ((BindingSource)source).DataSource;
}
var table = source as DataTable;
if (table != null)
{
    dt = table;
    var reportSource = new ReportDataSource("FactorReport", dt);
    this.reportViewer1.Reset();
    this.reportViewer1.ProcessingMode = ProcessingMode.Local;            
    this.reportViewer1.LocalReport.ReportPath = "FactorReport.rdlc";
    this.reportViewer1.LocalReport.DataSources.Clear();
    this.reportViewer1.LocalReport.DataSources.Add(reportSource);
    this.reportViewer1.RefreshReport();
}

So this is how the DataGridview looks:
enter image description here And then, this is the Reportviewer - note the two 'Rate' and 'Mult' rows appear at the bottom enter image description here enter image description here
So whilst it appears to work, I cannot see the values in the grid. Also, when the ages exceed 100, the ages are sorted incorrectly - can sorting be turned off? And on the assumption I can get this to work, is it possible to iterate through the ReportViewer and amend the column captions? A quick google tells me not at run-time?

MartinS
  • 111
  • 1
  • 14
  • You may find my new post useful:[Create RDLC report dynamically at run-time from a DataGridView](http://stackoverflow.com/questions/40362991/create-rdlc-report-dynamically-at-run-time-from-a-datagridview). – Reza Aghaei Nov 01 '16 at 19:22

2 Answers2

1

You should set name of columns in your DataTable which you ceate dynamically as DataSource of DataGridView correctly. They should be Age, Factor1, Factor2, ... , Factor10.

You created the report using those column names. So when you create a DataTable for your grid dynamically, you should set column names same as names you used when creating report.

How can I have same column names?

But you can fix the problem simply by creating a temporary DataTable containing Age, Factor1, ... , Factor10, filled by the original data table. Pass this table to the report and it will work.

How can I have same column titles which is shown in DataGridView?

The solution is column titles as parameters. Create 10 parameters in the report designer and set the title of columns of tablix in report using parameters but don't change name of columns. Those should be Age, Factor1, .... Then when you want to show the report, additional to the temp table which I mentioned above, pass column titles using parameters.

Another Idea

As another idea, you can have the report using exactly the same DataTable which contains all available columns and then when you want to show some columns in report, just pass some parameters to grid which indicates visibility of each column.

Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
  • OK, that makes sense - it can't match names so doesn't bind the data. The issue I have is that I don't know the column names until the user has selected them. I set up the reportviewer to test if I could get it working, in the hope that i could manipulate the RV headings, but unless I change my headings to factor1 etc, then it won't work. Thanks for your response. Back to the drawing board! – MartinS May 27 '16 at 10:40
  • Yes, column names are the issue. But you can fix them simply by creating a temporary `DataTable` containing `Age`, `Factor1`, ... , `Factor10`, filled by the original data table. Pass this table to the report and it will work. – Reza Aghaei May 27 '16 at 10:42
  • Thanks, but I need the report to have the actual headings, those seen in the first image (for this example) I set the headings in my viewer just to see if I could get the data to work. Now I understand where the issue is, I need to find a different approach. – MartinS May 27 '16 at 10:57
  • And the solution is passing them as parameters. Create 10 parameters in the report designer set the title of columns using parameters but name don't change name of columns. Those should be `Age`, `Factor1`, .... Then when you want to show the report, additional to the temp table which I mentioned in previous comment, pass column titles using parameters. The issue will be solved this way :) – Reza Aghaei May 27 '16 at 11:01
  • OK, thanks - I'll have to look at that as ReportViewer is totally new to me, so need to try and get my head around what you are suggesting. – MartinS May 27 '16 at 13:16
  • It's a mature suggestion ;) – Reza Aghaei May 27 '16 at 13:17
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/113159/discussion-between-martins-and-reza-aghaei). – MartinS May 27 '16 at 14:47
1

Maybe not the best/quickest solution but it works and with some additional changes to the visibility expressions, I'm able to only show the number of columns that have been selected.
I added 10 parameters to my reportviewer named Factor_Name_1 to Factor_Name_10, and checked 'Allow null value' in the properties when creating them. I then wrote some code to add the data for the parameters, storing the existing column names before renaming them to my Factor1, Factor2...Factor10 headings as follows (note I am not worried about in the first 'Age' column):

        // loop through the columns to create parameters...
        for (int i = 1; i < dt.Columns.Count; i++)
        {
            // get the name of the column...
            string factorName = dt.Columns[i].ColumnName;
            // define the new column name...
            string colName = string.Format("Factor_Name_{0}", i);
            // change the column name now we have stored the real name...
            dt.Columns[i].ColumnName = string.Format("Factor{0}", i);
            // generate the parameter...
            var rparam = new ReportParameter(colName, factorName);
            // add it to the parameter set for the control...
            this.reportViewer1.LocalReport.SetParameters(new[] { rparam });
        }

By re-setting the column names once I've created the associated parameter, the data will then bind correctly. All I had to do then, in my RDLC designer, is to replace the existing headings with the associated parameter values. Then, to hide the columns not selected, I set the visibility expression for the Parameter and Row Textboxes to:

=IIF(ISNOTHING(Parameters!Factor_Name_1.Value),True,False)
....
....
=IIF(ISNOTHING(Parameters!Factor_Name_10.Value),True,False)

Now, if I choose 1 or 10 columns, the viewer displays the correct number of columns and hides those not required. Am now working on repeating the 'age' column (already have the headings repeating) and adding a header/footer at runtime, but I currently have a report that displays the data I need with the correct headings.
With four items selected
With ten items selected Thanks to @Reza Aghaei for getting me on the right track.

MartinS
  • 111
  • 1
  • 14