Now, as promised, how to plumb in the custom rendering code for the cell level rendering:
The key function you will need to work in is an override to the RenderChildren function in your inherited gridview (protected override void RenderChildren(HtmlTextWriter writer)).
First off, you need to create a dictionary of your custom row renderers, one for each row in the controls Rows collection (of type GridViewRowCollection), indexed by the original row id (or a list of them in the same order as the original collection. As set up previously, the 'row renderer' is constructed by passing in the gridviewrow.
As you're overriding the child controls the one drawback is that you have to manually set up that table, using the htmlwriter to output the various rendering parameters:
if(this.BorderWidth != null)
writer.AddAttribute(HtmlTextWriterAttribute.Border, this.BorderWidth.ToString());
writer.AddAttribute(HtmlTextWriterAttribute.Cellspacing, this.CellSpacing.ToString());
writer.AddAttribute(HtmlTextWriterAttribute.Cellpadding, this.CellPadding.ToString());
if (this.CssClass != null)
writer.AddAttribute(HtmlTextWriterAttribute.Class, this.CssClass.ToString());
writer.RenderBeginTag(HtmlTextWriterTag.Table);
then the important bit - for the moment we'll go with the simplified case that you are displaying all your datarows in one long row (I'll cover wrapping in a future post).
Firstly, iterate over the columns in the GridView's Columns collection (of type DataControlFieldCollection) - there is one entry in this collection for every field (BoundField,TemplateField, etc.) specified in the markup using the gridview.
Within this loop you then need to:
- Tell the html writer to write out the <TR> tag:
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
- Loop over the rows in renderer list/dictionary, and within that call your renderer's custom cell Render Method:
Renderers[RowIndex].Render(writer, ColumnIndex, IsHeader);
- Tell the htmlwriter to write out the closing </TR> tag:
writer.RenderEndTag();
After the loops you then need to tell the html writer to write the closing </TABLE> tag with a final call to writer.RenderEndTag()
With the code detailed about you now have the full basic solution. I will post more on some additions that you will most likely want - wrapping, empty cell handling, and Custom CSS properties, all of which are used in the featured product grids on http://public.presalesadvisor.com/ - but hopefully this is enough to get you started.
General postings on bits and pieces of ASP.net and other Microsoft development that may be of use out there
Showing posts with label asp.net c# vertical gridview. Show all posts
Showing posts with label asp.net c# vertical gridview. Show all posts
Monday, 29 November 2010
Thursday, 25 November 2010
Vertical GridViews in ASP.net - Part 2b: Cell level rendering a GridViewRow
The key to the solution is the order in which the table cells are rendered out – in order to take over control of this we created a new class to wrap around the GridViewRow so that we could manually call the rendering on the actual cell we required. The structure of the class is quite simple:
If you’re not needing to output the cell as a header (i.e. render as a TH rather than a TD) all you need to do now is call the cell’s RenderControl method, passing in the HtmlTextWriter
If you do need to render as a header cell things aren’t quite as simple – header cells are actually set up during CreateChildControls as a different type - DataControlFieldHeaderCell rather than DataControlFieldCell.
The simplest solution we found was creating a new DataControlFieldHeaderCell and manually copying the properties that we were interesting in preserving from the original cell (in our case CssClass, HorizontalAlign, and VerticalAlign), and then reassign the child controls from the original cell to the new cell:
while (OriginalCell.Controls.Count > 0)
Once this is done call the header cell’s RenderControl as before.
I’ll leave it there for now, but will be post again soon with how to plumb this in to the standard control rendering
- A class variable to store the GridViewRow this is wrapping around
- A constructor that takes in a GridViewRow and assigns it to the class variable
- A render method that takes in a HTMLTextWriter, the index of the cell you want to render within the row, and a flag to indicate if this is to be rendered as a ‘header cell’ (more on the last in a post to follow)
If you’re not needing to output the cell as a header (i.e. render as a TH rather than a TD) all you need to do now is call the cell’s RenderControl method, passing in the HtmlTextWriter
If you do need to render as a header cell things aren’t quite as simple – header cells are actually set up during CreateChildControls as a different type - DataControlFieldHeaderCell rather than DataControlFieldCell.
The simplest solution we found was creating a new DataControlFieldHeaderCell and manually copying the properties that we were interesting in preserving from the original cell (in our case CssClass, HorizontalAlign, and VerticalAlign), and then reassign the child controls from the original cell to the new cell:
while (OriginalCell.Controls.Count > 0)
{
Control Child = OriginalCell.Controls[0];
HeaderCell.Controls.Add(Child);
}
Once this is done call the header cell’s RenderControl as before.
I’ll leave it there for now, but will be post again soon with how to plumb this in to the standard control rendering
Subscribe to:
Posts (Atom)