Aggregation Data Provider
Date: 16.09.2011
The Chart Web Part exists since version 1.1 of MatchPoint. It not only consumes from a data provider like the Data Grid and Composite Web Part, but also provides functionality to group the results and aggregate the values within the groups.
For a chart this functionality is quite essential. However, it would also be nice to have this feature in a Data Grid or Composite WebPart. This of course brings us to a custom data provider.
The aggregation data provider consumes its base values from another data provider (sort of chained data providers) and groups them based on a configurable grouping key and aggregation expression like in the Chart WebPart.
With this new data provider we can aggregate values from SharePoint lists, which currently would not be possible without coding. You can also implement, for example, a tag cloud (in fact the tag cloud on the Community Portal is implemented in exactly this way) with the help of a Composite Web Part by grouping the tags, counting their occurrence, and using the normalized counts to render the cloud.
Another important point is the caching, as it might take some time to group the values. Thanks to MatchPoint this comes free with the BaseDataProviderInstance.
The AggregationDataProvider configuration class looks like this:
public enum GroupingValueSortDirection
{
Ascending,
Descending,
None
}
[Serializable]
public class AggregatedField
{
public ExpressionString Expression = "AggregationValue + 1";
public string FieldName;
public ValueDisplayMode ValueDisplayMode;
public override string ToString()
{
return FieldName;
}
}
[Serializable]
public class AggregatedDataProvider: BaseDataProvider
{
public BaseDataProvider DataSource;
public AggregatedField[] Fields;
public ExpressionString GroupingExpression = "DataItem.GroupName";
[MemberDescriptor(MemberControlMode.Hidden)]
public ExpressionString AggregationExpression;
public GroupingValueSortDirection GroupingValueSortDirection;
[MemberDescriptor("Specifies how the data is cached. Choose 'User' if the query depends on the current user (e.g. user ID in the query or security trimmed data).")]
public CacheGranularity CacheGranularity;
[MemberDescriptor("Specifies how long the data is cached (in minutes).")]
public int CacheExpirationMinutes = 1;
protected override IEnumerable<FieldName> GetFieldNames(Core.MPInstance instance)
{
return (Fields ?? new AggregatedField[0]).Select(f => new FieldName(f.FieldName, f.FieldName));
}
public override BaseDataProviderInstance CreateInstance(IEnumerable<string> columnNames)
{
return new AggregatedDataProviderInstance(this, columnNames);
}
}
The AggregationProviderInstance is no big deal either. Check out the attached source file.
We actually like this new data provider so much that we are thinking about including it in our next release and even replacing the existing concept in the Chart Web Part with this new data provider.
Have fun! Feedback is appreciated ;-)