Skip to content

Instantly share code, notes, and snippets.

@steelheaddigital
Created July 30, 2012 23:01
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save steelheaddigital/3211605 to your computer and use it in GitHub Desktop.
Save steelheaddigital/3211605 to your computer and use it in GitHub Desktop.
An extension of the ASP.NET MVC WebGrid HTML helper to add a total row
In the ViewModel or Controller, create a new TotalWebGrid and return it to the view, just like with the normal WebGrid.
public TotalWebGrid Grid
{
get
{
return new TotalWebGrid(
source: stagingBillLines,
rowsPerPage: 10,
ajaxUpdateContainerId: "BillLines");
}
}
In the view add a TotalWebGridColumn. Set the Total property to true. This will sum this column and add the sum to the total row. Additionally you can assign a format and a CSS style to the total cell.
@{
var columns = new List<TotalWebGridColumn>();
columns.Add(new TotalWebGridColumn
{
ColumnName = "Charges",
Header = "Charges",
Total = true,
TotalFormat = "{0:C2}",
Style = "total"
});
}
@Model.Grid.GetHtml(columns: columns)
public class TotalWebGrid : WebGrid
{
//Extends the built in MVC WebGrid to add a total row
private bool _canPage;
public TotalWebGrid(IEnumerable<dynamic> source = null,
IEnumerable<string> columnNames = null,
string defaultSort = null,
int rowsPerPage = 10,
bool canPage = true,
bool canSort = true,
string ajaxUpdateContainerId = null,
string ajaxUpdateCallback = null,
string fieldNamePrefix = null,
string pageFieldName = null,
string selectionFieldName = null,
string sortFieldName = null,
string sortDirectionFieldName = null)
: base(
source,
columnNames,
defaultSort,
rowsPerPage,
canPage = true,
canSort,
ajaxUpdateContainerId,
ajaxUpdateCallback,
fieldNamePrefix,
pageFieldName,
selectionFieldName,
sortFieldName,
sortDirectionFieldName)
{
_canPage = canPage;
}
/// <param name="displayTotal">Whether the total row should be displayed</param>
/// <param name="totalRowStyle">Classes for styling the total row</param>
public IHtmlString GetHtml(
string tableStyle = null,
string headerStyle = null,
string footerStyle = null,
string rowStyle = null,
string alternatingRowStyle = null,
string selectedRowStyle = null,
string caption = null,
bool displayHeader = true,
bool fillEmptyRows = false,
string emptyRowCellValue = null,
IEnumerable<TotalWebGridColumn> columns = null,
IEnumerable<string> exclusions = null,
WebGridPagerModes mode = WebGridPagerModes.NextPrevious | WebGridPagerModes.Numeric,
string firstText = null,
string previousText = null,
string nextText = null,
string lastText = null,
int numericLinksCount = 5,
object htmlAttributes = null,
bool displayTotal = false,
string totalRowStyle = null)
{
Func<dynamic, object> footer = null;
if (_canPage && (PageCount > 1))
{
footer = item => Pager(mode, firstText, previousText, nextText, lastText, numericLinksCount);
}
return Table(tableStyle, headerStyle, footerStyle, rowStyle, alternatingRowStyle, selectedRowStyle, caption, displayHeader,
fillEmptyRows, emptyRowCellValue, columns, exclusions, displayTotal, totalRowStyle, footer: footer,
htmlAttributes: htmlAttributes);
}
public IHtmlString Table(
string tableStyle = null,
string headerStyle = null,
string footerStyle = null,
string rowStyle = null,
string alternatingRowStyle = null,
string selectedRowStyle = null,
string caption = null,
bool displayHeader = true,
bool fillEmptyRows = false,
string emptyRowCellValue = null,
IEnumerable<TotalWebGridColumn> columns = null,
IEnumerable<string> exclusions = null,
bool displayTotal = false,
string totalRowStyle = null,
Func<dynamic, object> footer = null,
object htmlAttributes = null)
{
IHtmlString html;
if (displayTotal)
{
string totalRow = BuildTotalRow(this.Rows, totalRowStyle, columns);
string baseHtml = base.Table(tableStyle, headerStyle, footerStyle, rowStyle, alternatingRowStyle, selectedRowStyle, caption, displayHeader, fillEmptyRows, emptyRowCellValue, columns, exclusions, footer, htmlAttributes).ToString();
string htmlWithTotal = baseHtml.Replace("</tbody></table>", totalRow);
html = new HtmlString(htmlWithTotal);
}
else
{
html = base.Table(tableStyle, headerStyle, footerStyle, rowStyle, alternatingRowStyle, selectedRowStyle, caption, displayHeader, fillEmptyRows, emptyRowCellValue, columns, exclusions, footer, htmlAttributes);
}
return html;
}
private string BuildTotalRow(IList<WebGridRow> rows, string totalRowStyle, IEnumerable<TotalWebGridColumn> columns)
{
var rowTag = string.Format("<tr class=\"{0}\">", totalRowStyle);
StringBuilder rowStringBuilder = new StringBuilder(rowTag);
foreach (var column in columns)
{
//Check if this column should be totaled
if (column.Total)
{
//Sum the column by looping through each row, getting the value, and adding it to the total
decimal columnTotal = 0;
foreach (var row in rows)
{
decimal cellValue = 0;
try
{
//Get the value in the column for this particular row
Type rowType = row.Value.GetType();
PropertyInfo rowProperty = rowType.GetProperty(column.ColumnName);
var propertyValue = rowProperty.GetValue(row.Value, null);
decimal.TryParse(propertyValue.ToString(), out cellValue);
}
//If exception is RuntimBinderException most likely the value is null and can't be summed anyway, so move on
catch (RuntimeBinderException) { }
columnTotal += cellValue;
}
//Format the total based on the user specified format
string totalFormat = column.TotalFormat == null ? "{0:0.00}" : column.TotalFormat;
var formattedTotal = string.Format(totalFormat, columnTotal);
//Create a new table cell tag containing the total and append it to the output string
var td = new TagBuilder("td");
td.MergeAttribute("class", column.TotalStyle);
td.InnerHtml = formattedTotal;
rowStringBuilder.Append(td.ToString());
}
else
{
//If the column shouldn't be totaled just append an empty table cell
var td = new TagBuilder("td");
rowStringBuilder.Append(td.ToString());
}
}
rowStringBuilder.Append("</tr></tbody></table>");
return rowStringBuilder.ToString();
}
}
public class TotalWebGridColumn : WebGridColumn
{
public bool Total { get; set; }
public string TotalFormat { get; set; }
public string TotalStyle { get; set; }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment