title: How do I implement a Telerik Custom Aggregate?
body: <p>I have a Telerik Grid which has a footer that needs to display column sums. However, one of the colums' data types is <code>TimeSpan</code>, which isn't supported by Telerik's Sum aggregate. I need to use <code>GridBoundColumnBuilder.Aggregate()</code> to add the aggregates. <strong>So I guess basically the question is how to reference my custom aggregate in telerik's Aggregate() method.</strong> And if you notice anything else I'm doing wrong, feel free to point it out :)Using <a href="http://www.telerik.com/support/kb/reporting/designing-reports/implementing-custom-aggregate-functions.aspx" rel="nofollow">this article</a>, I created a class for my custom aggregate, called <code>SumAggregate</code>, shown below. (note that this isn't finished- its taken from the article. It actually implements a totally different aggregate)</p>
  
  <p><strong>SumAggregate.cs</strong></p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Web;
  using Telerik.Web.Mvc;
  
  namespace TelerikPOC.CustomAggregates
  {
      public class SumAggregate : AggregateFunction
      {
          private System.Collections.Generic.List&lt;object&gt; distinctValues;
  
          /// &lt;summary&gt;
          /// Initializes the current aggregate function to its initial
          /// state ready to accumulate and merge values.
          /// &lt;/summary&gt;
          /// &lt;remarks&gt;
          /// This method is called every time the accumulation of values 
          /// must start over for a new subset of records from the data source.
          /// &lt;/remarks&gt;
          public void Init()
          {
              this.distinctValues = new System.Collections.Generic.List&lt;object&gt;();
          }
  
          /// &lt;summary&gt;
          /// Accumulates new argument values to the current aggregate function.
          /// &lt;/summary&gt;
          /// &lt;remarks&gt;
          /// This aggregate function accepts one argument:
          /// number - a numeric value to accumulate to the aggregate function;
          /// &lt;/remarks&gt;
          public void Accumulate(object[] values)
          {
              if (!distinctValues.Contains(values[0]))
              {
                  distinctValues.Add(values[0]);
              }
          }
  
          /// &lt;summary&gt;
          /// Merges the specified aggregate function to the current one.
          /// &lt;/summary&gt;
          /// &lt;param name="Aggregate"&gt;
          /// Specifies an aggregate function to be merged to the current one.
          /// &lt;/param&gt;
          /// &lt;remarks&gt;
          /// This method allows the reporting engine to merge two accumulated
          /// subsets of the same aggregate function into a single result.
          /// &lt;/remarks&gt;
          public void Merge(AggregateFunction aggregate)
          {
              // Accumulate the values of the specified aggregate function.
              System.Collections.Generic.List&lt;object&gt; sums1 =     ((SumAggregate)aggregate).distinctValues;
              foreach (object o in sums1)
              {
                  this.Accumulate(new object[] { o });
              }
          }
  
          /// &lt;summary&gt;
          /// Returns the currently accumulated value of the aggregate function.
          /// &lt;/summary&gt;
          /// &lt;returns&gt;
          /// The currently accumulated numeric value of the aggregate function.
          /// &lt;/returns&gt;
          public object GetValue()
          {
              return this.distinctValues.Count;
          }
      }
  }
  </code></pre>
  
  <p>And here is the code for adding the aggregates. This conflicts with the code below from <strong>index.cshtml</strong>, but I wanted to include both methods of adding aggregates just to give more options on the answer. This needs to be modified to use a custom aggregate rather than a built-in one, like it is using now.</p>
  
  <p><strong>GridHelper.cs</strong> (unfinished -- will add logic to loop through the columns and such later. By the way, if anyone would like to help me out with <em>that</em> too, I'd be very grateful, though I'll admit I haven't tried anything yet.)</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Web;
  using Telerik.Web.Mvc.UI.Fluent;
  using TelerikPOC.CustomAggregates;
  
  namespace TelerikPOC.Helpers
  {
      public class GridHelper
      {
          public static void AddAggregateToColumn(GridBoundColumnBuilder&lt;dynamic&gt; columnBuilder, string Aggregate)
          {
              switch (Aggregate)
              {
                  case "Sum":
                      {
                          columnBuilder.Aggregate(aggregates =&gt; aggregates.Sum())
                              .GroupFooterTemplate(result =&gt; "Sum:" + result.Sum)
                              .ClientFooterTemplate("Sum: &lt;#= Sum #&gt;")
                              .FooterTemplate(result =&gt; "Total: " + result.Sum);
                      }
                      break;
              }
          }
      }
  }
  </code></pre>
  
  <p>And then I'm using the <code>HtmlHelper</code> class to build/render the telerik grid, like this:</p>
  
  <p>From <strong>Index.cshtml</strong>: (be sure to read the comments to the right)</p>
  
  <pre><code>@{
      Html.Telerik()
      .Grid(Model)
      .Name("statisticalGrid")
      .Columns(columns =&gt;
      {
          columns.Bound(o =&gt; o.PlanID).Aggregate(something);         //This is probably going to be where 
          columns.Bound(o =&gt; o.SessionID).Aggregate(something);      //I need the help. Just not sure
          columns.Bound(o =&gt; o.TimeSpan).Aggregate(something);       //how to reference the custom
          columns.Bound(o =&gt; o.TimeSpanDouble).Aggregate(something); //aggregate here, in
      })                                                             //place of `something`
      .Sortable(sortable =&gt; sortable.Enabled(true))
      .Filterable()
      .Pageable(page =&gt; page.PageSize(25))
      .Reorderable(reorder =&gt; reorder.Columns(true))
      .Groupable(groupable =&gt; groupable.Enabled(true))
      .ClientEvents(events =&gt; events
          .OnColumnReorder("onReorder"))
      .Render();
  }
  </code></pre>
  
  <p>So I guess basically the question is how to reference my custom aggregate in telerik's <code>Aggregate()</code> method. And if you notice anything else I'm doing wrong, feel free to point it out :)</p>
  
  <p>Edit: Just noticed that I have to implement the method <code>CreateAggregateExpression(Expression, bool)</code> in the SumAggregate class. Not entirely sure how to implement it, though.</p>
  
  <p>Last Edit: I use a custom column builder method to build out the columms, so I'm not sure exactly how to do the formatting here. I was able to format the sum, but not the rest of the column, since outside the context of the telerik call I don't have access to the <code>item</code> variable. Here is basically what my column building logic is like:</p>
  
  <p>In the telerik code,</p>
  
  <pre><code>.Columns(a =&gt; GridHelper.GenerateColumns(a, Model.SelectedReport))
  </code></pre>
  
  <p>And generate columns looks something like:</p>
  
  <pre><code>public static void GenerateColumns(GridColumnFactory&lt;dynamic&gt; columnFactory, Company.Project.Data.Entity.Report reportStructure)
          {
              foreach (var columnLayout in reportStructure.ReportCols.OrderBy(o =&gt; o.ColumnSequence))
              {
                  GridBoundColumnBuilder&lt;dynamic&gt; columnBuilder = columnFactory.Bound(columnLayout.ColumnType);
                  //do other stuff here (add aggregates, formatting, etc)
              }
  </code></pre>
  
  <p>So how would I do the formatting in this context?</p>