Introduction
Usually, when you want to calculate a complex summary for tabular data, let's say displayed in an ASP.NET GridView
, you need to write code for three logical parts:
- init your summary calculation state variables - counters, sums, etc.
- handle row changed event to increment calculation state
- get result based on state variables
And of course, you need these state variables declaration. Sometimes even additional structures to keep your page code clean. You can significantly simplify/replace this with the help of a simple library for evaluating aggregate expressions.
See project site on CodePlex.
Background
Main project brief description:
ExpressionEngine
- contains all the classes responsible for expression evaluation.
Using the Code
Let's see how to replace the standard approach for GridView
summary with expressions. To make it simpler, let's start from a grid with one column, and AVG
as summary:
<asp:GridView ShowFooter="true" AutoGenerateColumns="false"
runat="server" onrowdatabound="OnRowDataBound">
<Columns>
<asp:BoundField DataField="Column1" HeaderText="Column1"/>
</Columns>
</asp:GridView>
In the code-behind, we need to define the OnRowDataBound
function to process every single row:
protected void OnRowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
_count++;
_sum += ((MyDataItemClass)e.Row.DataItem).Column1;
}
if (e.Row.RowType == DataControlRowType.Footer)
{
if (_count != 0)
e.Row.Cells[0].Text = string.Format("AVG(Column1) = {0}", _sum / _count);
}
}
And the state variables:
private int _count = 0;
private double _sum = 0;
And the same with expressions summary:
Instead of a state variable, we are defining an AggregateExpressionEvaluator
instance with summary formula:
AggregateExpressionEvaluator summary1 = new AggregateExpressionEvaluator("AVG(Column1)");
Updated OnRowDataBound
function:
protected void OnRowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
ReflectionValueProvider provider = new ReflectionValueProvider(e.Row.DataItem);
summary1.RowChanged(provider);
}
if (e.Row.RowType == DataControlRowType.Footer)
{
e.Row.Cells[0].Text = string.Format("AVG(Column1) = {0}", summary1.GetResult());
}
}
That's it.
If you have several complex summaries in your grid, it can significantly simplify your code. Also, with expressions, it's much easier to change the calculation algorithm, or even load it dynamically.
See example in AspNetGridViewExpressionSummary\Default.aspx.cs.
Actually you can calculate summaries even without a grid control. See the below example of calculation of AVG
salary for an array of Employee
objects:
public class Employee
{
public int Salary { get; set; }
}
Employee[] employees;
AggregateExpressionEvaluator evaluator = new AggregateExpressionEvaluator("AVG(Salary)");
foreach (object obj in employees)
{
ReflectionValueProvider provider = new ReflectionValueProvider(obj);
evaluator.RowChanged(provider);
}
double avg = evaluator.GetResult();
See example in TestExpressionParser\AggregateTestDataItem.cs.
History
- Version 1 - 16th March 2013 - First version.
Software Architect - Net. C#, JavaScript
Web Site: http://icocentre.com/