For this task, I needed to modify an existing report to allow for dynamic headers and columns. I was able to accomplish this in the report_DataInitialize, although I believe I read the Report Start is the recommended place. When I tried using that, I found that I did not have the data I needed to calculate how many label and columns I would need. So far report_DataInitialize has worked just fine...keeping my fingers crossed.
This is a subreport by the way. Previously, I had the header labels in the parent report, so I did also have to add a group header to make this work right.
So pretty much, I create as many new text boxes I need for the report in a loop, making each have a unique id, and allow some spacing in between. Then I add the text box to the detail section at the defined point that has been 'calculated'.
For the header, I do the same, but create labels, and then add them to the group header.
I also populate the columns with data in the report_FetchData, using the same looping logic to find the text box name and then give it a value to display.
For the most part this wasn't too bad of a task. I took a little digging about but I think it works.
private void report_DataInitialize(object sender, System.EventArgs e)
{
if (this.Classroom.Books.Count > 0)
{
float i = 0.0F;
foreach (Book book in Classroom.Books)
{
bool isActive = book.Active ?? false;
if (isActive){
StringBuilder sb = new StringBuilder("bk_");
sb.Append(book.ID);
string fieldName = sb.ToString();
this.Fields.Add(fieldName);
TextBox tb = new TextBox();
tb.Name = fieldName;
tb.DataField = fieldName;
tb.Height = .2F;
tb.Width = 1.1F;
tb.Alignment = TextAlignment.Right;
i = (i == 0.0F) ? 1.6F : i + 1.1F;
this.Sections["detail"].Controls.Add(tb);
this.Sections["detail"].Controls[tb.Name].Location = new PointF(i, 0);
Label lbl = new Label();
lbl.Name = fieldName + "lbl";
lbl.Text = gp.Description;
lbl.Height = .2F;
lbl.Width = 1.1F;
lbl.Alignment = TextAlignment.Right;
this.Sections["groupHeader1"].Controls.Add(lbl);
this.Sections["groupHeader1"].Controls[lbl.Name].Location = new PointF(i, 0);
}
}
}
}