This is a migrated thread and some comments may be shown as answers.

Aggregate function on multiple columns

12 Answers 637 Views
GridView
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Wasif Jahangir
Top achievements
Rank 1
Wasif Jahangir asked on 08 Jul 2010, 07:38 AM
I have three columns in my grid i.e.
UnitPrice
Quantity
Discount

and need to show one total in footer.
calc will be like this: (Quantity * UnitPrice * Discount%)
i can do individual columns calculations. but not on multiple columns

thanks in advance

12 Answers, 1 is accepted

Sort by
0
Vlad
Telerik team
answered on 08 Jul 2010, 08:32 AM
Hello,

 You can create any custom aggregate similar to this demo.

All the best,
Vlad
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
0
Wasif Jahangir
Top achievements
Rank 1
answered on 08 Jul 2010, 09:05 AM
Sorry by mistake i posted in Silverlight forum.
this problem belongs to WPF.
can u guide me w.r.t. WPF?
0
Vlad
Telerik team
answered on 08 Jul 2010, 09:08 AM
Hi,

 You can use exactly the same approach in WPF. Here is the WPF version of the same example:
http://demos.telerik.com/wpf/?GridView/CustomAggregates

All the best,
Vlad
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
0
Tim
Top achievements
Rank 1
answered on 05 Oct 2010, 09:45 PM
I stumbled across this thread while searching the forum and I have a related question. 

I based my aggregate function on the example cited above (the demo) and I was dismayed that the DataMemberBinding to a property of type ulong (in my case, a disk drive capacity in bytes) does not work - there is a linq error about unable to find a matching function.  Changing the property to be double and it works, but that's not feasible for my application.  Why doesn't ulong work?

The other disappointing thing was that although the GridView starts out grouped and aggregated as expected, removing the aggregation and dragging the same column header back (ungroup-regroup) and it no longer rolls up as I would expect.  Is there a sample out there which maybe starts out life as not grouped/aggregated, and aggregates when the table is grouped?

In particular, if I had a table of computers, volumes, capacities, free, used, I'd like to group by computer and have the capacity/free/used roll up all disk drives on that computer.

Tim
0
Vlad
Telerik team
answered on 06 Oct 2010, 07:13 AM
Hi Tim,

 You need to customize the code of the demo to satisfy your scenario. Please check Statistics class, StdDev method for more info. 

Kind regards,
Vlad
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
0
Tim
Top achievements
Rank 1
answered on 06 Oct 2010, 02:25 PM
I will illustrate the problem with code snippets.

First, I tried to use the built-in sum function like so:

<TelerikGridView:RadGridView.GroupDescriptors>
  <TelerikData:GroupDescriptor Member="Nickname"  SortDirection="Ascending">
    <TelerikData:GroupDescriptor.AggregateFunctions>
      <TelerikData:SumFunction SourceField="TotalCapacityGB" Caption="Total"/>
    </TelerikData:GroupDescriptor.AggregateFunctions>
  </TelerikData:GroupDescriptor>
</TelerikGridView:RadGridView.GroupDescriptors>

on the following DataContext object:

public class ComputerInfo
{
  public string Nickname { get { return Filer.DisplayName; } }
  public ulong TotalCapacityGB { get { return TotalSizeBytes; } }
}

Which results in the following exception:

Error: An unknown error has occurred.
Detail: System.InvalidOperationException
No generic method 'Sum' on type 'System.Linq.Enumerable' is compatible with the supplied type arguments and arguments. No type arguments should be provided if the method is non-generic.
   at System.Linq.Expressions.Expression.FindMethod(Type type, String methodName, Type[] typeArgs, Expression[] args, BindingFlags flags)
   at System.Linq.Expressions.Expression.Call(Type type, String methodName, Type[] typeArguments, Expression[] arguments)
   at Telerik.Windows.Data.Expressions.EnumerableSelectorAggregateFunctionExpressionBuilder.CreateMethodCallExpression(LambdaExpression memberSelectorExpression)
   at Telerik.Windows.Data.Expressions.EnumerableSelectorAggregateFunctionExpressionBuilder.CreateAggregateExpression()
   at Telerik.Windows.Data.EnumerableSelectorAggregateFunction.CreateAggregateExpression(Expression enumerableExpression)
   at Telerik.Windows.Data.Expressions.GroupDescriptorExpressionBuilder.<ProjectionPropertyValueExpressions>b__3(AggregateFunction f)
   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at Telerik.Windows.Data.Expressions.GroupDescriptorExpressionBuilder.CreateProjectionInitExpression()
   at Telerik.Windows.Data.Expressions.GroupDescriptorExpressionBuilder.CreateAggregateFunctionsProjectionMemberBinding()
   at Telerik.Windows.Data.Expressions.GroupDescriptorExpressionBuilder.<CreateMemberBindings>d__0.MoveNext()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Dynamic.Utils.CollectionExtensions.ToReadOnly[T](IEnumerable`1 enumerable)
   at System.Linq.Expressions.Expression.MemberInit(NewExpression newExpression, IEnumerable`1 bindings)
   at Telerik.Windows.Data.Expressions.GroupDescriptorExpressionBuilder.CreateSelectBodyExpression()
   at Telerik.Windows.Data.Expressions.GroupDescriptorExpressionBuilder.CreateResultSelectorExpression()
   at Telerik.Windows.Data.Expressions.GroupDescriptorExpressionBuilder.get_ResultSelectorExpression()
   at Telerik.Windows.Data.Expressions.GroupDescriptorExpressionBuilderBase.CreateQuery()
   at Telerik.Windows.Data.Expressions.GroupDescriptorCollectionExpressionBuilder.CreateQuery()
   at Telerik.Windows.Data.QueryableExtensions.GroupBy(IQueryable source, IEnumerable`1 groupDescriptors)
   at Telerik.Windows.Data.QueryableCollectionView.CreateView()
   at Telerik.Windows.Data.QueryableCollectionView.get_QueryableView()
   at Telerik.Windows.Data.QueryableCollectionView.CreateInternalList()
   at Telerik.Windows.Data.QueryableCollectionView.EnsureInternalList()
   at Telerik.Windows.Data.QueryableCollectionView.get_InternalList()
   at Telerik.Windows.Data.QueryableCollectionView.GroupedIndexOf(Object item)
   at Telerik.Windows.Data.QueryableCollectionView.InternalIndexOf(Object item)
   at Telerik.Windows.Data.QueryableCollectionView.IndexOf(Object item)
   at Telerik.Windows.Data.QueryableCollectionView.AdjustCollectionChangedIndex(Object item, Int32 index)
   at Telerik.Windows.Data.QueryableCollectionView.AdjustNewIndices(NotifyCollectionChangedEventArgs args)
   at Telerik.Windows.Data.QueryableCollectionView.ProcessSynchronousCollectionChanged(NotifyCollectionChangedEventArgs args)
   at Telerik.Windows.Data.QueryableCollectionView.ProcessCollectionChanged(NotifyCollectionChangedEventArgs args)
   at Telerik.Windows.Data.QueryableCollectionView.OnSourceCollectionChanged(Object sender, NotifyCollectionChangedEventArgs args)
   at Telerik.Windows.Data.QueryableCollectionView.Telerik.Windows.Data.IWeakEventListener<System.Collections.Specialized.NotifyCollectionChangedEventArgs>.ReceiveWeakEvent(Object sender, NotifyCollectionChangedEventArgs args)
   at Telerik.Windows.Data.WeakEvent.WeakListener`1.Handler(Object sender, TArgs args)
   at System.Collections.ObjectModel.ObservableCollection`1.OnCollectionChanged(NotifyCollectionChangedEventArgs e)
   at System.Collections.ObjectModel.ObservableCollection`1.InsertItem(Int32 index, T item)
   at System.Collections.ObjectModel.Collection`1.Add(T item)

Changing the property type to double and it works the same as the demo.  Changing it to be double is undesirable.

public class ComputerInfo
{
  public string Nickname { get { return Filer.DisplayName; } }
  public double TotalCapacityGB { get { return TotalSizeBytes; } }
}

Second, I followed your demo (http://demos.telerik.com/silverlight/#GridView/CustomAggregates) and modified the StdDev method

using System;
using System.Collections.Generic;
using System.Linq;
using Telerik.Windows.Data;
 
namespace blah
{
    public class SumCapacityFunction : EnumerableSelectorAggregateFunction
    {
        protected override string AggregateMethodName
        {
            get { return "AggregateCapacity"; }
        }
 
        protected override System.Type ExtensionMethodsType
        {
            get { return typeof (CapacityAggregate); }
        }
    }
 
    public static class CapacityAggregate
    {
        public static double AggregateCapacity<T>(IEnumerable<T> source, Func<T, double> selector)
        {
            IEnumerable<double> values = from i in source select Convert.ToDouble(selector(i));
            return values.Sum();
        }
    }
}

but was greeted with exactly the same exception.  The problem is that the call sequence does not like ulong - this is the same in both cases.  Once I can get the AggregateCapacity<T> method invoked on type ulong, then I can customize it to roll-up all three values, or at least try.

My second area of concern ("dismay") was that the grouping was not sticky.  I.e., if I ungroup and regroup by the same column, the rollup goes away.  I was kind of surprised by this.  If I set an initial sort descriptor, and then sort by something else, I can always sort by the initial one again.  I would like to have a way to custom group and don't see one in the otherwise very helpful demo.

Thanks,
Tim


0
Tolga Erdogus
Top achievements
Rank 1
answered on 07 Oct 2010, 09:25 PM
I too, just stumbled upon the type mismatch error in the lambda selector...
0
Vlad
Telerik team
answered on 08 Oct 2010, 07:24 AM
Hi Tim,

Your aggregate methods are still with double - as I said you need to rework them to work with ulong.

All the best,

Vlad
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
0
preeti
Top achievements
Rank 1
answered on 29 Dec 2010, 10:57 AM
Hi Vlad,

i have grid collumn which is of type float. and the same exception is thrown when i try to use the SumFunction.
i get this error
No generic method 'Sum' on type 'System.Linq.Enumerable' is compatible with the supplied type arguments and arguments. No type arguments should be provided if the method is non-generic.

XAML code

 

 

 

<telGrid:GridViewDataColumn.AggregateFunctions>
<telerikData:SumFunction Caption="Net Annualized Revenue YTD($):"/>
</telGrid:GridViewDataColumn.AggregateFunctions>

 

0
Vlad
Telerik team
answered on 29 Dec 2010, 11:00 AM
Hi,

 You've missed to set SourceField. 

Greetings,
Vlad
the Telerik team
Browse the videos here>> to help you get started with RadControls for Silverlight
0
preeti
Top achievements
Rank 1
answered on 29 Dec 2010, 11:08 AM

Hi Vlad i have tried doing the way it is mentioned in the link

 

 

 

<telGrid:GridViewDataColumn Header="Annualized Rev YTD($)"   TextAlignment="Right"  IsReadOnly="True" IsFilterable="True" DataMemberBinding="{Binding ANNUALIZEDYTDREVENUE,Converter={StaticResource textFormatConverter},ConverterParameter=\{0:n\}}" >
                       <telGrid:GridViewDataColumn.AggregateFunctions>
                           <local:SumFunction Caption="Net Annualized Revenue YTD($):" />
                           <!--<telerikData:SumFunction Caption="Net Annualized Revenue YTD($):" />-->
                       </telGrid:GridViewDataColumn.AggregateFunctions>                    
                   </telGrid:GridViewDataColumn>

public static class Statistics
   {
       public static Double Sum<T>(IEnumerable<T> source, Func<T, Double> selector)
       {
           return source.Select(selector).Aggregate(Double.MaxValue, (t1, t2) => t1 + t2);
       }
   }
   public class SumFunction : EnumerableSelectorAggregateFunction
   {
       protected override string AggregateMethodName
       {
           get
           {
               // which method of the ExtensionMethodsType will handle the summation 
               return "Sum";
           }
       }
       // assign new type to handle summation 
       protected override Type ExtensionMethodsType
       {
           get
           {
               return typeof(Statistics);
           }
       }
   }
 Still the issue exixts. can u tell me where i am going wrong?

0
preeti
Top achievements
Rank 1
answered on 29 Dec 2010, 12:18 PM
Even after adding source i am faceing the same problem
<telGrid:GridViewDataColumn.AggregateFunctions>
                                              <telerikData:SumFunction SourceField="ANNUALIZEDYTDREVENUE" Caption="Net Annualized Revenue YTD($):" />
                        </telGrid:GridViewDataColumn.AggregateFunctions>
 plz tell me what is wrong
Tags
GridView
Asked by
Wasif Jahangir
Top achievements
Rank 1
Answers by
Vlad
Telerik team
Wasif Jahangir
Top achievements
Rank 1
Tim
Top achievements
Rank 1
Tolga Erdogus
Top achievements
Rank 1
preeti
Top achievements
Rank 1
Share this question
or