/// <summary> /// If multiple rows are necessary, the passed row becomes the current row becomes the first row. /// The new row is returned. /// </summary> /// <param name="gv"></param> /// <returns></returns> private GridViewRow FormatMultiRowHeader(GridViewEx gv) { // Start by assuming that we will need a new row // Set row index to -2 to indicate that this is the second header row. // GridViewMatrixCell looks at this to determine whether the first row or the second row of the header should // be rendered GridViewRow rowAdded = new GridViewRow(ROW_SECOND_LINE_HEADER, -1, DataControlRowType.Header, DataControlRowState.Normal); for (int i = 0; i < this.Cells.Count; ++i) { DataControlFieldCell cellOrig = (DataControlFieldCell)this.Cells[i]; if (!cellOrig.ContainingField.Visible) { // Ignore invisible columns continue; } char[] seperator = new char[] { '|' }; string[] tokens = cellOrig.ContainingField.HeaderText.Split(seperator, StringSplitOptions.RemoveEmptyEntries); //string[] expressions = gv.SortExpression.Split(';'); //List<string> listSortExpressions = new List<string>(expressions); switch (tokens.Length) { case 0: // Empty header cellOrig.RowSpan = 2; break; case 1: // single line header cellOrig.RowSpan = 2; cellOrig.VerticalAlign = VerticalAlign.Middle; cellOrig.Text = tokens[0]; break; case 2: // Tow header rows are in fact needed cellOrig.Text = tokens[0]; DataControlFieldCell cellNew; if (cellOrig.ContainingField is IHasCustomCells) { IHasCustomCells cancreate = cellOrig.ContainingField as IHasCustomCells; cellNew = cancreate.CreateCell(DataControlCellType.Header); } else { cellNew = new GridViewExHeaderCell(gv, cellOrig.ContainingField); } cellNew.Text = tokens[1]; rowAdded.Cells.Add(cellNew); break; default: throw new NotSupportedException("At most one pipe character is allowed in the header text"); } } if (rowAdded.Cells.Count == 0) { // Revert all the rowspans back to default foreach (TableCell cell in this.Cells) { cell.RowSpan = 0; } rowAdded = null; } else { SetColumnSpan(); } return(rowAdded); }
/// <summary> /// The function retains information of all the columns implementing the interface <see cref="INeedsSummaries" />. /// </summary> /// <param name="writer"></param> private void RenderMasterRowFooter(HtmlTextWriter writer) { if (!this.Grid.ShowFooter) { return; } // Script uses this class to exclude subtotal rows from becoming selectable this.Grid.FooterStyle.CssClass += " gvex-subtotal-row"; this.Grid.FooterStyle.AddAttributesToRender(writer); writer.RenderBeginTag(HtmlTextWriterTag.Tr); var query = this.Grid.Columns.Cast <DataControlField>() .Select((p, i) => new { Column = p, Index = i }) .Where(p => p.Column.Visible); foreach (var colInfo in query) { IHasCustomCells customCellField = colInfo.Column as IHasCustomCells; if (customCellField == null) { colInfo.Column.FooterStyle.AddAttributesToRender(writer); writer.RenderBeginTag(HtmlTextWriterTag.Td); INeedsSummaries summaryCol = colInfo.Column as INeedsSummaries; if (summaryCol == null) { if (string.IsNullOrEmpty(colInfo.Column.FooterText)) { writer.Write(" "); } else { writer.Write("Subtotal"); } } else { string formatString = summaryCol.DataFooterFormatString; object[] values; switch (summaryCol.DataSummaryCalculation) { case SummaryCalculationType.None: case SummaryCalculationType.DataSource: formatString = " "; values = new object[0]; break; case SummaryCalculationType.ValueWeightedAverage: if (string.IsNullOrEmpty(formatString)) { formatString = "{0}"; } SummaryData data = _subtotalInfo.Subtotals[colInfo.Index]; values = new object[] { data.Values[0] / data.Values[1] }; break; case SummaryCalculationType.ValueSummation: if (string.IsNullOrEmpty(formatString)) { formatString = "{0}"; } values = _subtotalInfo.Subtotals[colInfo.Index].Values.Cast <object>().ToArray(); break; default: throw new NotImplementedException(); } writer.Write(formatString, values); } writer.RenderEndTag(); //td } else { customCellField.RenderSubtotals(this, writer, _subtotalInfo.FirstRowIndex, _subtotalInfo.LastRowIndex); } } writer.RenderEndTag(); // tr }