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

Telerik MVC Grid having Multiple Groups and Issue with aggregates

7 Answers 140 Views
Grid
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Dipak
Top achievements
Rank 1
Dipak asked on 29 Aug 2012, 06:23 PM
I have Telerik MVC grid and have 2 groups. and i wants to do sum for each group level and total. Here is my code.

View Code
<%= Html.Telerik().Grid<OutsourceSummary>()
.Name("OutsourceSummaryGRid")
.DataKeys(DataKeys => DataKeys.Add(o => o.FormatID).RouteKey("FormatId"))
.DataBinding(dataBinding =>
dataBinding
.Ajax()
.Select("_OutsourcedSummary", "Job", new { JobId = Model.JobID))
.Columns(columns =>
{
columns.Bound(o => o.FormatID).Width(80).ReadOnly(true).Hidden(true);
columns.Bound(o => o.FormatName).Width(350).Sortable(false);
columns.Bound(o => o.Quantity)
.Aggregate(aggreages => aggreages.Sum())
.Format("{0:n0}")
.ClientFooterTemplate("Total : <#= typeof Sum != 'undefined' ? $.telerik.formatString('{0:n0}',Sum) : 0 #>")
.ClientGroupFooterTemplate("<div style=\"width:100%; text-align:right\"> Total : <#= typeof Sum != 'undefined' ? $.telerik.formatString('{0:n0}',Sum) : 0 #></div>")
.FooterHtmlAttributes(new { @style = "text-align:right;" })
.HeaderHtmlAttributes(new { @style = "text-align:right;" })
.Width(150)
.Sortable(false)
.Filterable(false)
.Title("Quantity")
.HtmlAttributes(new { align = "right" });
})
.Pageable(page => page.PageSize(100))
.Sortable()
.Filterable()
.EnableCustomBinding(true)
.Groupable(settings => settings
.Groups(groups => groups.Add(o => o.FacilityName))
.Groups(groups => groups.Add(o => o.Operation))
.Visible(false))
%>

Here is my Controller and helper code.

[GridAction(EnableCustomBinding = true)]
    public ActionResult _OutsourcedSummary(int JobId, GridCommand command)
    {
        int listcnt = 0;
  
        IEnumerable<OutsourceSummary> data = _FormatRepo.GetOutsourcedSummary(0, JobId);
  
        var data1 = (IQueryable<OutsourceSummary>)data.AsQueryable();
  
        data1 = data1.ApplyPaging(command.Page, command.PageSize);
  
        listcnt = data.Count();
  
        var aggregates = new Dictionary<string, object>();
  
        if (command.Aggregates.Any())
        {
            aggregates["Quantity"] = new { Sum = data1.Sum(p => p.Quantity) };
        }
  
        if (command.GroupDescriptors.Any())
        {
            var groupdata = AppendOutsourceGrouping(data, command.GroupDescriptors);
  
            return View(new GridModel
            {
                Data = groupdata,
                Total = listcnt,
                Aggregates = aggregates
            });
        }
        else
        {
  
            return View(new GridModel
            {
                Data = data,
                Total = listcnt,
                Aggregates = aggregates
            });
        }
  
    }
  
  
    private IEnumerable AppendOutsourceGrouping(IEnumerable<OutsourceSummary> data, IList<GroupDescriptor> groupDescriptors)
    {
  
        Func<IEnumerable<OutsourceSummary>, IEnumerable<AggregateFunctionsGroup>> selector = null;
        foreach (var group in groupDescriptors.Reverse())
        {
            if (selector == null)
            {
                if (group.Member == "FacilityName")
                {
                    selector = jobs => BuildInnerGroup(jobs, o => o.FacilityName);
                }
                else if (group.Member == "Operation")
                {
                    selector = jobs => BuildInnerGroup(jobs, o => o.Operation);
                }
            }
            else
            {
                if (group.Member == "FacilityName")
                {
                    selector = BuildGroup(o => o.FacilityName, selector);
                }
                else if (group.Member == "Operation")
                {
                    selector = BuildGroup(o => o.Operation, selector);
                }
            }
        }
  
        return selector.Invoke(data).ToList();
    }
  
    private static Func<IEnumerable<OutsourceSummary>, IEnumerable<AggregateFunctionsGroup>> BuildGroup<T>(Func<OutsourceSummary, T> groupSelector, Func<IEnumerable<OutsourceSummary>, IEnumerable<AggregateFunctionsGroup>> selectorBuilder)
    {
        var tempSelector = selectorBuilder;
  
        return g => g.GroupBy(groupSelector)
                     .Select(c => new AggregateFunctionsGroup
                     {
                         Key = c.Key,
                         HasSubgroups = true,
                         Items = tempSelector.Invoke(c),
                     });
    }
    private static IEnumerable<AggregateFunctionsGroup> BuildInnerGroup<T>(IEnumerable<OutsourceSummary> group, Func<OutsourceSummary, T> groupSelector)
    {
  
        return group.GroupBy(groupSelector)
                .Select(i => new AggregateFunctionsGroup
                {
                    Key = i.Key,
                    Items = i.ToList(),
                    ItemCount = i.Count()
                });
    }

I tried to do aggregates but its only doing at top level, not at group level.

Appriciate for any help.

Thanks,



7 Answers, 1 is accepted

Sort by
0
Georgi
Top achievements
Rank 2
answered on 03 Sep 2012, 08:09 AM
I have the same problem and I am looking for a solution, but so far I have nothing. From all the articles that I have read, I understood
that when using CustomBinding, you can't use aggregates in ClientGroupFooterTemplate and ClientGroupHeaderTemplate. Maybe someone from the Telerik team can confirm this or suggest a solution.
0
Georgi
Top achievements
Rank 2
answered on 04 Sep 2012, 07:38 AM
I've made some progress. I've inherited AggregateFunctionsGroup and made MyAggregates property in the new class, because Aggregates property in AggregateFunctionsGroup has no setter. I saw trough debugging that it works for the first group I make. But the problem is that I don't know what should the Dictionary Key name be, so I can pass it to the GridModel and the aggregate value would be displayed in place. And the other problem of course is that this only works for the first group. If I add another one, the result is the same.


private static Func<IEnumerable<StockDocument>, IEnumerable<MyAggregateFunctionsGroup>>
            BuildGroup<T>(Func<StockDocument, T> groupSelector, Func<IEnumerable<StockDocument>,
            IEnumerable<MyAggregateFunctionsGroup>> selectorBuilder)
        {
            var tempSelector = selectorBuilder;
            return g => g.GroupBy(groupSelector)
                         .Select(c => new MyAggregateFunctionsGroup
                         {
                             Key = c.Key,
                             HasSubgroups = true,
                             Items = tempSelector.Invoke(c).ToList(),
                             MyAggregates = new Dictionary<string, object>()
                             {
                                {c.Key + "TotalPrice", new { Sum = c.Sum(i => i.TotalPrice) }}
                             }
                         });
        }
 
 
 
        private static IEnumerable<MyAggregateFunctionsGroup> BuildInnerGroup<T>(IEnumerable<StockDocument>
            group, Func<StockDocument, T> groupSelector)
        {
            return group.GroupBy(groupSelector)
                    .Select(i => new MyAggregateFunctionsGroup
                    {
                        Key = i.Key,
                        Items = i.ToList(),
                        MyAggregates = new Dictionary<string, object>()
                             {
                                {i.Key + "TotalPrice", new { Sum = i.Sum(asd => asd.TotalPrice) }}
                             }
                    });
        }
 
class MyAggregateFunctionsGroup : AggregateFunctionsGroup
    {
        public Dictionary<string, object> MyAggregates { get; set; }
 
    }
0
Dipak
Top achievements
Rank 1
answered on 04 Sep 2012, 11:41 AM
Hi Georgi,

thanks for your reply. i have done the same things for single group, but i don't know how to do it for groups has 3 level.
0
Georgi
Top achievements
Rank 2
answered on 04 Sep 2012, 11:54 AM
Hi Dipak,
did you manage to display the aggregate in the grid's ClientGroupFooterTemplate for the first group at least?
0
Dipak
Top achievements
Rank 1
answered on 05 Sep 2012, 12:02 PM
Yes, its working for one group.  do you need code? If so let me know i will find it and post here,
0
Georgi
Top achievements
Rank 2
answered on 05 Sep 2012, 12:31 PM
Yes, can you please post the code here.
Thanks
0
Luis
Top achievements
Rank 1
answered on 01 Nov 2012, 08:13 PM
Hi, you guys should try this: http://tgh.codeplex.com/
Tags
Grid
Asked by
Dipak
Top achievements
Rank 1
Answers by
Georgi
Top achievements
Rank 2
Dipak
Top achievements
Rank 1
Luis
Top achievements
Rank 1
Share this question
or