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

Determining range of the datasource that comprises a group

1 Answer 48 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Fred
Top achievements
Rank 1
Fred asked on 26 Feb 2012, 09:27 PM
Hello,

I have a radgrid that has groups nested several layers deep. For each group I have a footer that has several custom aggregate fields. The values for these need to be calculated based upon the actual data in the underlying datasource (most of which is not exposed to radgrid in the form of columns). How can I determine what rows from the datasource make up the group? Something in the form of StartIndex and EndIndex would be absolutely ideal.

Thanks,

Fred

1 Answer, 1 is accepted

Sort by
0
Tsvetina
Telerik team
answered on 01 Mar 2012, 02:49 PM
Hi Fred,

If you have multiple groups the approach to pick up the items of a certain group would require some custom code. First, you can make a recursive call to get a collection of all headers and their corresponding GridDataItems. Then, perform a calculation for each group and assign the total to the footer. Here is a sample code snippet to build the collection of group headers:
protected Dictionary<GridGroupHeaderItem, List<GridItem>> BuildGroupHeaderCollection(GridTableView tableView)
{
 
    Dictionary<GridGroupHeaderItem, List<GridItem>> itemHeaders = new Dictionary<GridGroupHeaderItem, List<GridItem>>();
    //below you will need to pass the relevant GridTableView object
    var allGroups = tableView.GetItems(GridItemType.GroupHeader);
    foreach (GridGroupHeaderItem group in allGroups)
    {
        itemHeaders[group] = PopulateGroups(group, itemHeaders);
    }
    return itemHeaders;
}
 
protected List<GridItem> PopulateGroups(GridGroupHeaderItem headerItem, Dictionary<GridGroupHeaderItem, List<GridItem>> headersChildItems)
{
    List<GridItem> items = new List<GridItem>();
    foreach (var item in headerItem.GetChildItems())
    {
        if (item is GridGroupHeaderItem)
        {
            items.AddRange(PopulateGroups((item as GridGroupHeaderItem), headersChildItems));
        }
        else if (item is GridDataItem)
        {
            items.Add(item);
        }
    }
    if (items.Count > 0)
    {
        if (headersChildItems.ContainsKey(headerItem))
        {
            headersChildItems[headerItem].AddRange(items);
        }
        else
        {
            headersChildItems.Add(headerItem, items);
        }
    }
    return items;
}

You can gather the GridGroupFooters in a corrsponding order if you use the ItemCreated event of RadGrid:
Dictionary<GridTableView, List<GridGroupFooterItem>> footers = new Dictionary<GridTableView, List<GridGroupFooterItem>>();
void RadGrid1_ItemCreated(object sender, GridItemEventArgs e)
{
    if (e.Item is GridGroupFooterItem)
    {
        GridGroupFooterItem item = e.Item as GridGroupFooterItem;
        GridTableView tbView = item.NamingContainer as GridTableView;
        if (footers.Keys.Contains(tbView))
        {
            footers[tbView].Add(item);
        }
        else
        {
            footers.Add(tbView, new List<GridGroupFooterItem>() { item });
        }
    }
}

Then, using the two collections you can do the following on RadGrid PreRender event:
Dictionary<GridGroupHeaderItem, List<GridItem>> headerCollection = BuildGroupHeaderCollection(RadGrid1.MasterTableView);              
{
    int count = 0;
    foreach (var item in headerCollection)
    {
        var sum = item.Value.Cast<GridDataItem>().Select(d => d.DataItem).Cast<DataRowView>().Select(rv => rv.Row["UnitPrice"]).Cast<Decimal>().Sum();
        var searchedFooterItem = footers[nestedViewItem.NestedTableViews[0]].Skip(count).Take(1).FirstOrDefault();
        searchedFooterItem["UnitPrice"].Text = sum.ToString();
        count++;
    }
}

You could simplify the code a bit as it is a part of an example that addresses the same problem in a hierarchical grid, so the first two code snippets work with respect to having multiple GridTableViews.

Also, the last bit that calculates the total is adjusted for a grid bound to a DataTable, if you have a custom class there, so if you have a custom class there, you will need to adjust this line of code to work with it:
var sum = item.Value.Cast<GridDataItem>().Select(d => d.DataItem).Cast<DataRowView>().Select(rv => rv.Row["UnitPrice"]).Cast<Decimal>().Sum();

I hope this helps.

All the best,
Tsvetina
the Telerik team
If you want to get updates on new releases, tips and tricks and sneak peeks at our product labs directly from the developers working on the RadControls for ASP.NET AJAX, subscribe to their blog feed now.
Tags
Grid
Asked by
Fred
Top achievements
Rank 1
Answers by
Tsvetina
Telerik team
Share this question
or