For .Net WPF XamPivotGrid:
Can you tell me if Calculated Measures are supported in FlatDataSource. Basically we will like to provide our own calculation for aggregating measures (e.g. weighted average instead of plain average).
I do see that Measures have aggregator which takes enum value and there are references to ByChildreen, ByAccount and Calculated.
I do not see any example and unable to determine how to use it.
Thanks
Hi
Sorry for delay.
You can apply different aggregation function as you use follow code
IOlapViewModel viewModel = pivotGrid.DataSource;
viewModel.SetMeasureAggregator((IMeasureViewModel)viewModel.Measures[0], MeasureAggregator.Count);
viewModel.RefreshGrid();
For now only Sum, Min, Max, Count and Average have implementation. We work to implement and another type of aggregation function in the future releases.
Todor
Does new version (2011), support it?
We added support for custom aggregators in 11.1 version. Here you can see a sample how to do this.
RegardsTodor
Thanks a lot.
I actually have same imports. I had to modify definitions for Funcs:
private
Func<object, object> _getValue;
private Func<object, object> _getWeight;
as well as specify data type for Cast() method and it runs:
IList dataItems = items.Cast<DataRowMetadata>().Select(drm => drm.DataObject).ToList();
Thanks a lot again,
Alex
If it helps, I am targeting framework 4 and my imports are
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Infragistics.Olap;
using Infragistics.Olap.FlatData;
I don't think there are any special libraries
Hi,
I am trying to achieve similar goal for my WA properties and hoped to steal your custom aggregator :-)
Not able to compile it though . Do you use some specific libs for Func and Linq ?
I am having the following comp. time errors :
Error 231 Using the generic type 'System.Func<TResult>' requires 1 type arguments
Error 236 The call is ambiguous between the following methods or properties: 'Stealth.Components.PivotGrid.Model.DerivedData.IgWeightedAverageAggregator.Evaluate(Infragistics.Olap.IAggregationResult, Infragistics.Olap.IAggregateable, System.Collections.IEnumerable)' and 'Stealth.Components.PivotGrid.Model.DerivedData.IgWeightedAverageAggregator.Evaluate(Infragistics.Olap.IAggregationResult, Infragistics.Olap.IAggregateable, System.Collections.IEnumerable)'
Error 233 'System.Linq.Queryable.Cast<TResult>(System.Linq.IQueryable)' is a 'method', which is not valid in the given context
Can you please help me to get your aggreagtor running ?
Thanks a lot in advance,
This works
public class IgWeightedAverageCache { /// /// sum(Weight * Value) /// private double _numerator = 0; /// /// sum(Weight) /// private double _denominator = 0; internal IgWeightedAverageCache() { } internal IgWeightedAverageCache(double numerator, double denominator) { _numerator = numerator; _denominator = denominator; } internal double WeightedAverage { get { return _numerator/_denominator; } } public void Add(double weight, double value) { _numerator += weight*value; _denominator += weight; } } public class IgWeightedAverageResult : IAggregationResult { private readonly IgWeightedAverageCache _cache; public IgWeightedAverageResult() { this._cache = new IgWeightedAverageCache(); } public IgWeightedAverageCache Cache { get { return this._cache; } } public double Value { get { return this.Cache.WeightedAverage; } set { throw new NotImplementedException(); } } object IAggregationResult.Value { get { return this.Value; } } object IAggregationResult.Cache { get { return this.Cache; } } } /// /// TODO: Flyweight? /// public class IgWeightedAverageAggregator : IAggregator { private readonly string _valuePropertyName; private readonly string _weightPropertyName; private Func _getValue; private Func _getWeight; public IgWeightedAverageAggregator(string valuePropName, string weightPropName) { _valuePropertyName = valuePropName; _weightPropertyName = weightPropName; } public string Identity { get; set; } private void InitReflection(object item) { if (_getValue == null) { lock (this) { if (_getValue == null) { Type itemsType = item.GetType(); var valuePropertyInfo = itemsType.GetProperty(_valuePropertyName); var weightPropertyInfo = itemsType.GetProperty(_weightPropertyName); _getValue = ReflectionHelper.CreatePropertyGetMethod(valuePropertyInfo); _getWeight = ReflectionHelper.CreatePropertyGetMethod(weightPropertyInfo); } } } } public IAggregationResult Evaluate(IAggregationResult oldResult, IAggregateable aggregateable, IEnumerable items) { var result = new IgWeightedAverageResult(); IList dataItems = items.Cast().Select(drm => drm.DataObject).ToList(); if (dataItems.Count > 0) { InitReflection(dataItems[0]); foreach (object dataItem in dataItems) { var weight = (double?) _getWeight(dataItem); var value = (double?)_getValue(dataItem); if (weight != null && value != null) { result.Cache.Add(weight.Value, value.Value); } } } return result; } public IAggregationResult Evaluate(IAggregationResult oldResult, IAggregateable aggregateable, IEnumerable items) { return this.Evaluate((oldResult as IgWeightedAverageResult), aggregateable, items); } public IAggregationResult Evaluate(IAggregationResult oldResult, double value) { throw new NotImplementedException(); } public IAggregationResult Evaluate(IAggregationResult oldResult, object value) { throw new NotImplementedException(); } }
I am looking at your examples. Is it actually possible to do a weighted average? For example, if I have a Value and Weight columns, the aggregation of Value should be sum(Value[i]*Weight[i])/sum(weight[i])? Can you give an example of that?