I have created windows form that acts as report loader. I have created also two RDLC reports by report wizard and it automatically created dataset for those two reports. Now I have two datasets: sparcsn4DataSet.xsd and sparcsn4DataSet1.xsd that are using stored procedure and passes two parameters (dateFrom/ dateTo). I have a problem with binding dataset depending on the status:
if (idRep.Equals("extraMove"))
It is quite easy to bind dataset to reportview, if you have one report.
but what if you have more than one? I can always create another form with another reportviewer but this is not an option (what if you have 10 reports/datasets), this is definitely out of question?
There should be a way to bind dataset to reportviewer... Does anyone have idea, how I can solve binding problem depending on the status?
if (idRep.Equals("extraMove"))
{
this.AGCT_ServiceEventReportTableAdapter.Fill(this.sparcsn4DataSet.AGCT_ServiceEventReport, d1,d2);
}
else if (idRep.Equals("stripStuff"))
{
this.AGCT_StripStuffReportTableAdapter.Fill(this.sparcsn4DataSet1.AGCT_StripStuffReport, d1, d2);
}
else
{
MessageBox.Show("Ooops, something went wrong...!");
}
This is ReportForm.cs that have reportviewer on it:
namespace NavisReportLoader
{
public partial class ReportForm : Form
{
public DateTime d1;
public DateTime d2;
public string dat1;
public string dat2;
public string idRep;
public ReportForm()
{
InitializeComponent();
}
public void passParam(string dateFrom, string dateTo, string date1, string date2)
{
//ispravi ovo
d1 = Convert.ToDateTime(dateFrom);
d2 = Convert.ToDateTime(dateTo);
dat1 = date1;
dat2 = date2;
}
public void report(string id)
{
idRep = id;
}
private void ReportForm_Load(object sender, EventArgs e)
{
ReportParameter[] param = new ReportParameter[2];
param[0] = new ReportParameter("date1", dat1);
param[1] = new ReportParameter("date2", dat2);
this.reportViewer1.LocalReport.SetParameters(param);
if (idRep.Equals("extraMove"))
{
this.AGCT_ServiceEventReportTableAdapter.Fill(this.sparcsn4DataSet.AGCT_ServiceEventReport, d1,d2);
}
else if (idRep.Equals("stripStuff"))
{
this.AGCT_StripStuffReportTableAdapter.Fill(this.sparcsn4DataSet1.AGCT_StripStuffReport, d1, d2);
}
else
{
MessageBox.Show("Ooops, something went wrong...!");
}
this.reportViewer1.RefreshReport();
}
}
}
OK, trying to figure it out, yesterday I found a solution which was acceptable to me, so I wanted to share with others:
1.st you need to create a class model with properties so it will be added in dataset:
example:
namespace NavisReportLoader.App_Data
{
public class ExtraMoveModel
{
public string EventType { get; set; }
public int EventCount { get; set; }
public int Num20 { get; set; }
public int Num40 { get; set; }
public int Num45 { get; set; }
public int TEU { get; set; }
public float Cargo { get; set; }
public float Tare { get; set; }
public float Total { get; set; }
}
}
after that you need to create plain simple class for connecting to the database and call the stored procedure, pass the parameters and read using data reader output. In my example, I have added this into a list and enumerate my model:
example:
public class ExtraMoveDataSet
{
string connectionString = @"Data Source=sampleDB; Initial Catalog=test; User Id=sa; Password=test";
public IEnumerable<ExtraMoveModel> extraMove(DateTime dateFrom, DateTime dateTo)
{
var tempList = new List<ExtraMoveModel>();
//string connectionString = @"Data Source=nsqltest; Initial Catalog=sparcsn4; User Id=sa; Password=lo02Nova";
SqlConnection conn = new SqlConnection(connectionString);
SqlCommand cmd = new SqlCommand("AGCT_ServiceEventReport", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@dateFrom", dateFrom);
cmd.Parameters.AddWithValue("@dateTo", dateTo);
conn.Open();
using (var dr = cmd.ExecuteReader())
{
while (dr.Read())
{
var temp = new ExtraMoveModel();
temp.EventType = dr["event_type"].ToString();
temp.EventCount = Convert.ToInt32(dr["CNT"]);
temp.Num20 = Convert.ToInt32(dr["NUM20"]);
temp.Num40 = Convert.ToInt32(dr["NUM40"]);
temp.Num45 = Convert.ToInt32(dr["NUM45"]);
temp.TEU = Convert.ToInt32(dr["TEU"]);
temp.Cargo = float.Parse(dr["Cargo"].ToString(),new CultureInfo("hr-HR"));
temp.Tare = float.Parse(dr["Tare"].ToString(),new CultureInfo("hr-HR"));
temp.Total = float.Parse(dr["Total"].ToString(),new CultureInfo("hr-HR"));
tempList.Add(temp);
}
}
conn.Close();
return tempList;
}
- step is to create dataset that will have same name as properties from a model.
- step create report on which you will bind dataset.
finally you can add it to the reportViewer1
private void ReportForm_Load(object sender, EventArgs e)
{
ExtraMoveDataSet emDS = new ExtraMoveDataSet();
if (idRep.Equals("extraMove"))
{
ReportParameter[] param = new ReportParameter[2];
param[0] = new ReportParameter("date1", dat1);
param[1] = new ReportParameter("date2", dat2);
//string path = Directory.GetCurrentDirectory();
//string replace = path.Replace("\\bin\\Debug", "") + "\\App_Data\\"+"ReportExtraMove.rdlc";
var ret = emDS.extraMove(d1, d2);
ReportDataSource rds = new ReportDataSource("extraMove", ret.ToArray());
this.reportViewer1.LocalReport.DataSources.Add(rds);
//this.reportViewer1.LocalReport.ReportPath = replace;
this.reportViewer1.LocalReport.ReportEmbeddedResource = "NavisReportLoader.App_Data.ReportExtraMove.rdlc";
this.reportViewer1.LocalReport.SetParameters(param);
this.reportViewer1.RefreshReport();
}
}
I hope this will help other to speed things up.
cheers!
I spent some time on the same problem. I'm using VS 2013 where the dataset is connected through an automatically-created BindingSource in the report form. If you create the report and add all the required elements, everything works fine. If you (say) add a table later, the BindingSources get out-of-step, or aren't created.
Edit the report form Design view, click on the ReportViewer object and use the little 'Tasks' arrowhead in the top r.h. corner. Either select 'Rebind Data Sources' or 'Choose Data Sources' to check they are correctly bound.
To force Visual Studio to create automatically the bindingsource, you have to create the report (.rdlc) first. With a datasource linked, when you add the component (reportviewer) and link the component with the name of the report as shown in your image, once you select the report, it will automatically create a binding source with the name that you use when you created the design.