Calculated column in RadGridView for Silverlight + math expressions

Thursday, January 28, 2010 by Pavel Pavlov | Comments 6

When the data layer does not allow to perform calculations we often need to harness the UI.

Here is a a simple case  - in our business object we have the Price and the Count properties. We will have RadGridView to calculate the Total  for us in a calculated column.

 

calculated_column

 

If you peek into the sample project you will notice we are using a pretty standard Silverlight approach :

We bind the value of the calculated column with a Binding Converter :

<telerik:GridViewDataColumn 
					Header="Total" 
					Background="Bisque" 
					DataMemberBinding="{Binding Converter={StaticResource CalculatingConverter}}" 
					TextAlignment="Right" />
 
The calculation “logic” is in the Convert method of CalculatingConverter.cs
 
  public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return ((Item)value).Price * ((Item)value).Count;
        }
 
For simple scenarios it should do the trick . The bad thing is we have hardcoded the converter to our Item class with Price and Count properties.
What if we need a more dynamic approach  - to give the RadGridView a string Expression like “Price*Count  and have it evaluate and calculate for us. 
 
The Poor Man’s Expression Parser
 
A popular hack when a simple expression parser is needed in Silverlight is to call the javascript eval function from the hosting browser window. 
Here is how our “dynamic expression” converter will look like : 
public class CalculatingConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            string stringexpression = BuildExpression(value, parameter.ToString());
            return HtmlPage.Window.Invoke("eval", stringexpression);
        }
        private string BuildExpression(object value, string parameter)
        {
            StringBuilder sb = new StringBuilder(parameter);
            foreach (PropertyInfo propertyInfo in value.GetType().GetProperties())
            {
                if (propertyInfo.CanRead)
                {
                    object o = propertyInfo.GetValue(value, null);
                    sb.Replace(propertyInfo.Name, o.ToString());
                }
            } 
            return sb.ToString();
        }
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
 
This gives us the power to pass the column a string expression - ‘Price*Count’ ( as a parameter of the value converter ): 
 
DataMemberBinding="{Binding Converter={StaticResource CalculatingConverter},ConverterParameter='Price*Count'}" 
 
For your copy/paste needs please download the 

 

[UPDATE]

If we move the calculation logic where it belongs  - the data layer, we may benefit from the INotifyPropertyChanged interface. This way the user will be able to change values in cells and get the totals recalculated in a spreadsheet alike manner. This approach is demonstrated in

 

 

.

6 Comments

  • Vlad 14 May 2010
    Hi,

    We are trying to use your example here.  It works for static data.  However, if the values changed, the calculated column is not changing.  Do you have any solution to the Calculated Column that changes dynamically at runtime?


    Thanks
  • chrishnaa 07 Jun 2010
    When we defined the columns to be displayed in the report (static report), we used Aggregate function and Footer Text property on the numerical fields . This gives us a total field when data is not grouped and automatically generates subtotals when grouped using drag and drop functionality.  Is there is any other means of adding Total to the grid
  • Hưng Phạm 01 Jul 2010
    Hi
    when I use "dynamic expression". It run good with IE + Google Chrome, but it didn't run on firefox.
    how to run it by firefox.
    firefox return error "function eval must be called directly, and not by way of a function of another name" detail Error 4004.
  • Satrajit Choudhury 03 Jul 2010
    Hi,

    What would the syntax be in the XAML page for showing the total in the footer of calculated column?

    I tried using the code below, I was able to get the data in the calculated column, but When I tried showing the data in the footer of this calculated column it did not work.

     

    <

     

     

    grid:GridViewDataColumn Header="FY2011-Q4" IsReadOnly="True" DataMemberBinding="{Binding Converter={StaticResource CalculatingConverter},ConverterParameter='FY_1_Q4'}" HeaderTextAlignment="Center" UniqueName="FY_1_Q4">

     

     

     

     


    <grid:GridViewDataColumn.AggregateFunctions>

     

     

     

     

    <data:SumFunction Caption="Sum (In LCY): " SourceField="FY_1_Q4"/>

     

     

     

     

    </grid:GridViewDataColumn.AggregateFunctions>

     

     

     

     

    </grid:GridViewDataColumn>

     

  • Mark 01 Apr 2011
    An example of creating a sum in the footer of a calculated column is still not available.
  • Ganesh 22 Jul 2011
    Hi,
    My requirement is to display the sum of all values of radgridview in a textbox, please give some idea.
    Thanks
    Ganesh

Add comment

  1. Formatting options
       
     
     
     
     
       
  2. (optional, emails won't be shown on public pages)
  3. (optional)