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

About Reorder by SumFunction Value

9 Answers 162 Views
GridView
This is a migrated thread and some comments may be shown as answers.
tao
Top achievements
Rank 1
tao asked on 16 Dec 2010, 09:09 AM
<gridView:RadGridView x:Name="textGridView"
              ItemsSource="{Binding testList}"
              Style="{StaticResource _gridStyle}">
         
        <gridView:RadGridView.Columns>
            <gridView:GridViewDataColumn Header="Name"  DataMemberBinding="{Binding Name}"/>
            <gridView:GridViewDataColumn Header="Description" DataMemberBinding="{Binding Description}" />
 <gridView:GridViewDataColumn Header="Grade" DataMemberBinding="{Binding Grade}" UniqueName="_Grade">
<telerik:GridViewDataColumn.AggregateFunctions>
                        <telerik:CountFunction Caption="Total customers:" />
                    </telerik:GridViewDataColumn.AggregateFunctions>
<telerik:GridViewDataColumn.AggregateFunctions>
                        <telerik:CountFunction Caption="Total customers:" />
                    </telerik:GridViewDataColumn.AggregateFunctions>
  <telerik:GridViewDataColumn.AggregateFunctions>
                        <telerik:CountFunction Caption="Total customers:" />
                    </telerik:GridViewDataColumn.AggregateFunctions>
  <telerik:GridViewDataColumn.AggregateFunctions>
                        <telerik:CountFunction Caption="Total customers:" />
                    </telerik:GridViewDataColumn.AggregateFunctions>
  <telerik:GridViewDataColumn.AggregateFunctions>
                        <telerik:CountFunction Caption="Total customers:" />
                    </telerik:GridViewDataColumn.AggregateFunctions>
<telerik:GridViewDataColumn.AggregateFunctions>
        <telerik:CountFunction Caption="Total customers:" />
    </telerik:GridViewDataColumn.AggregateFunctions>
<telerik:GridViewDataColumn.AggregateFunctions>
        <telerik:CountFunction Caption="Total customers:" />
    </telerik:GridViewDataColumn.AggregateFunctions>
<telerik:GridViewDataColumn.AggregateFunctions>
        <telerik:CountFunction Caption="Total customers:" />
    </telerik:GridViewDataColumn.AggregateFunctions>
<telerik:GridViewDataColumn.AggregateFunctions>
        <telerik:CountFunction Caption="Total customers:" />
    </telerik:GridViewDataColumn.AggregateFunctions>
<telerik:GridViewDataColumn.AggregateFunctions>
        <telerik:CountFunction Caption="Total customers:" />
    </telerik:GridViewDataColumn.AggregateFunctions>
<telerik:GridViewDataColumn.AggregateFunctions>
        <telerik:CountFunction Caption="Total customers:" />
    </telerik:GridViewDataColumn.AggregateFunctions>    
<telerik:GridViewDataColumn.AggregateFunctions>
        <telerik:CountFunction Caption="Total customers:" />
    </telerik:GridViewDataColumn.AggregateFunctions>    
<telerik:GridViewDataColumn.AggregateFunctions>
<telerik:SumFunction/>
</telerik:GridViewDataColumn.AggregateFunctions>
</gridView:GridViewDataColumn>
        </gridView:RadGridView.Columns>
 
            <gridView:RadGridView.GroupDescriptors>
                <telerikData:GroupDescriptor DisplayContent="Name" Member="Name" SortDirection="Ascending" />
        </gridView:RadGridView.GroupDescriptors>
</gridView:RadGridView>
<telerik:GridViewDataColumn.AggregateFunctions>
        <telerik:CountFunction Caption="Total customers:" />
    </telerik:GridViewDataColumn.AggregateFunctions>

Now when I click the groupdescriptor, gridview reordered by "Name".
If I want to reorder by Value of Sum "_Grade" after clicked the groupdescriptor, What should I do?
<telerik:GridViewDataColumn.AggregateFunctions>
        <telerik:CountFunction Caption="Total customers:" />
    </telerik:GridViewDataColumn.AggregateFunctions>
<telerik:GridViewDataColumn.AggregateFunctions>
        <telerik:CountFunction Caption="Total customers:" />
    </telerik:GridViewDataColumn.AggregateFunctions>

 

9 Answers, 1 is accepted

Sort by
0
Maya
Telerik team
answered on 16 Dec 2010, 09:17 AM
Hello tao,

You need to override the CreateGroupSortExpression() method and implement an expression for sorting according to the result of the aggregate functions. I am sending you a sample project illustrating how to achieve the desired functionality. 

All the best,
Maya
the Telerik team
Browse the videos here>> to help you get started with RadControls for Silverlight
0
Justin Wilson
Top achievements
Rank 1
answered on 12 Apr 2011, 06:30 PM
Thanks for the example.  I have multiple aggregate functions in one column.  So when that column is grouped I have several aggregate results for the grouped row.  The client wants to be able to sort the rows by each of these aggregates.  I cannot seem to figure out a way to allow the client to sort by each aggregate function.  Any guidance you could provide would be helpful.

Thanks,
Justin
0
Maya
Telerik team
answered on 14 Apr 2011, 07:49 AM
Hi Justin Wilson,

May you provide a bit more details about your exact requirement ? Do you want to perform multiple sorting or sorting based only on a single aggregate function from the aggregates in the group ? How do you want to visualize the different sorting - how do you want to choose which aggregate to sort by ?
 

All the best,
Maya
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
Justin Wilson
Top achievements
Rank 1
answered on 14 Apr 2011, 12:03 PM
I have columns in my grid with several aggregates.  When the column is grouped I only need the client to be able to sort by one aggregate at a time.  I don't need multiple sorting for this.  I have no idea how to visualize this.  I was thinking maybe a drop down right above the grid with the aggregates in it.  The user would select which aggregate to sort by.  Then I would rebind the data to the grid with the proper index of the selected aggregate passed into the constructer of the SortGridDescritptor class.  If you have a better Idea of how to visualize this please let me know.  I can't find any information on anyone else doing this or how it would look.

Thanks
Justin Wilson
0
Maya
Telerik team
answered on 20 Apr 2011, 09:44 AM
Hello Justin Wilson,

If you want to be able to sort based on different aggregate functions, you may slightly extend the SortingGroupDescriptor class:

public class SortingGroupDescriptor : GroupDescriptor
    {
        private AggregateFunction sortFunction;
        public AggregateFunction SortFunction
        {
            get
            {
                return sortFunction;
            }
            set
            {
                sortFunction = value;
 
                this.OnPropertyChanged("SortFunction");
            }
        }
 
        public override Expression CreateGroupSortExpression(Expression groupingExpression)
        {
            if (this.SortFunction != null)
            {
                return this.SortFunction.CreateAggregateExpression(groupingExpression);
            }
            else
            {
                return base.CreateGroupSortExpression(groupingExpression);
            }
        }

In this case the SortFunction will give us the information towards which function you want to sort. Afterwards, depending on your custom implementation, you may set the function as follows:
var descriptor = this.playersGrid.GroupDescriptors[0] as SortingGroupDescriptor;
descriptor.SortFunction = descriptor.AggregateFunctions[1];

Once you change the SortFunction, sorting will be performed again when clicking on the group panel cell.
Still, I am sending you a sample project illustrating the proposed solution.
 


Greetings,
Maya
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
Megan Vee
Top achievements
Rank 1
answered on 06 Oct 2011, 05:11 PM
Maya - 
I have the same issue as Justin.
But not what you have in the example.
Instead of 2 aggregates for one column, I have multiple columns with aggregates.
So let's say number had a sum aggregate and position had a sum aggregate.
I want to be able to drag country (and state and continent, etc) into the grouped by section
and then I want to be able to click the number header and have the aggregates sort by number
or click the position header and sort by position.

Is this possible?
Can you provide a sample?

It would be very much appreciated.
Thanks, Megan
0
Maya
Telerik team
answered on 07 Oct 2011, 08:02 AM
Hello Megan Vee,

You could use the same approach as the one illustrated above by creating a SortingGroupDescriptor-s. Each descriptor created will be sorted based on the values of its aggregate function. 
If you want to add groups through the UI, you could handle the Grouping event and define such SortingGroupDescriptor instead of the default one - ColumnGroupDescriptor. For example:

private void playersGrid_Grouping(object sender, GridViewGroupingEventArgs e)
        {
            if (e.Action == GroupingEventAction.Place)
            {
                e.Cancel = true;
                ColumnGroupDescriptor currentDescriptor = e.GroupDescriptor as ColumnGroupDescriptor;
 
                SortingGroupDescriptor sortingDescriptor = new SortingGroupDescriptor();
                sortingDescriptor.Member = (currentDescriptor.Column as GridViewDataColumn).DataMemberBinding.Path.Path;
                foreach (AggregateFunction function in (currentDescriptor.Column as GridViewDataColumn).AggregateFunctions)
                {
                    sortingDescriptor.AggregateFunctions.Add(function);
                }
                this.playersGrid.GroupDescriptors.Add(sortingDescriptor);
            }
        }

The code above is based on the project attached at the beginning of the thread - SortGroupsByAggregates.
 

Best wishes,
Maya
the Telerik team

Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

0
Megan Vee
Top achievements
Rank 1
answered on 11 Oct 2011, 03:43 PM
Maya - 
Thanks so much for your help. With a bunch more customization in the sort and group functions, I was able to fulfill the requirements.

Notes for others, if interested:
I added some logic into the sorting function in order to sort all groups (and in the same direction)
I also added a function to get the sortgroupdescriptor and sortfundtion - for reuse.

private void CurrentGridView_Sorting(object sender, GridViewSortingEventArgs e)
        {
            //capture sorting state so all levels can be sorted the same way
            SortingState sortState = e.OldSortingState;
 
            //if group, sort by agg
            if (CurrentGridView.GroupCount > 0)
            {
                //sort for each group
                for (int i = 0; i < CurrentGridView.GroupCount; i++)
                {
                    //get descriptor (and set sortfunction)
                    var descriptor = GetGroupSortFunctionDescriptor(e.Column.UniqueName, i);
 
                    //set sort direction
                    switch (sortState)
                    {
                        case SortingState.Ascending:
                            //descriptor.SortDirection = null;
                            descriptor.SortDirection = ListSortDirection.Descending;
                            break;
                        case SortingState.Descending:
                            //descriptor.SortDirection = ListSortDirection.Ascending;
                            descriptor.SortDirection = null;
                            break;
                        case SortingState.None:
                            //descriptor.SortDirection = ListSortDirection.Descending;
                            descriptor.SortDirection = ListSortDirection.Ascending;
                            break;
                    }
                }
            }
            //else sort by non-agg values
            else
            {
                GridViewBoundColumnBase c = (GridViewBoundColumnBase)e.Column;
                string cDataType = c.DataType.ToString();
 
                if (cDataType.Contains("System.Int32"))
                {
                    switch (sortState)
                    {
                        case SortingState.Ascending:
                            e.NewSortingState = SortingState.None;
                            break;
                        case SortingState.Descending:
                            e.NewSortingState = SortingState.Ascending;
                            break;
                        case SortingState.None:
                            e.NewSortingState = SortingState.Descending;
                            break;
                    }
                }
            }
        }
 
        private SortingGroupDescriptor GetGroupSortFunctionDescriptor(string columnName, int groupId)
        {
            var descriptor = CurrentGridView.GroupDescriptors[groupId] as SortingGroupDescriptor;
 
            //get aggregate id
            int id = 0;
            foreach (AggregateFunction function in descriptor.AggregateFunctions)
            {
                //TODO: Figure out a way to sort by functions with captions (string columns)
                //"Name" (which is the 'count:' field) is hard-coded right now - this is not ideal
                if (function.FunctionName.Contains(columnName) || (function.FunctionName.Contains("Count") && columnName == "Name"))
                {
                    break;
                }
                id++;
            }
 
            //set sort to clicked column's aggregate
            descriptor.SortFunction = descriptor.AggregateFunctions[id];
            return descriptor;
        }

Then in the grouping function, I added some logic to sort the groups based on the previous sort column and direction when a new group is placed:
private void CurrentGridView_Grouping(object sender, GridViewGroupingEventArgs e)
{
    if (e.Action == GroupingEventAction.Place)
    {
        e.Cancel = true;
        ColumnGroupDescriptor currentDescriptor = e.GroupDescriptor as ColumnGroupDescriptor;
 
        SortingGroupDescriptor sortingDescriptor = new SortingGroupDescriptor();
        sortingDescriptor.Member = (currentDescriptor.Column as GridViewBoundColumnBase).DataMemberBinding.Path.Path;
        foreach (AggregateFunction function in (currentDescriptor.Column as GridViewBoundColumnBase).AggregateFunctions)
        {
            sortingDescriptor.AggregateFunctions.Add(function);
        }
        this.CurrentGridView.GroupDescriptors.Add(sortingDescriptor);
 
        //if first group, set sort to current non-aggregate sort column
        if (CurrentGridView.GroupDescriptors.Count == 1)
        {
            //get previous non-aggregate sort column
            var previousDescriptor = CurrentGridView.SortDescriptors[0] as SortDescriptor;
            //get current group descriptor (and sortfunction)
            var descriptor = GetGroupSortFunctionDescriptor(previousDescriptor.Member.ToString(), 0);
            //set sort function and direction
            sortingDescriptor.SortFunction = descriptor.SortFunction;
            sortingDescriptor.SortDirection = CurrentGridView.SortDescriptors[0].SortDirection;
        }
        //else not first group, agg sorting already in place, set sort to current aggregate sort column
        else
        {
            //get previous descriptor (and sortfunction)
            var previousDescriptor = CurrentGridView.GroupDescriptors[0] as SortingGroupDescriptor;
            //set sort function and direction
            sortingDescriptor.SortFunction = previousDescriptor.SortFunction;
            sortingDescriptor.SortDirection = previousDescriptor.SortDirection;
        }
    }
 
    //placing group or removing a group when there is more than one group already
    if (e.Action != GroupingEventAction.Remove || CurrentGridView.GroupCount > 1)
    {
        CurrentGridView.Columns[0].Width = 200;
    }
    else
    {
        CurrentGridView.Columns[0].Width = 25;
    }
}

HTH someone out there. ;)
-Megan
0
Pete
Top achievements
Rank 1
answered on 27 Feb 2013, 04:42 PM
I'm using the SortGroupByDifferentAggregatea.zip with Studio 2012 with Silverlight 5.0 and RadControls for Silverlight Q2 2012
The issue I'm having is that if I drop the column "number" from the group by in the UI and re-add it the aggregates don't show anymore.
So I added the aggregate to the column definition:
<telerik:RadGridView.Columns>
<telerik:GridViewDataColumn Header="Name" DataMemberBinding="{Binding Name}">
</telerik:GridViewDataColumn>
<telerik:GridViewDataColumn Header="Number" DataMemberBinding="{Binding Number}">
<telerik:GridViewDataColumn.AggregateFunctions>
<data:SumFunction Caption="Sum: " SourceField="Number"/>
<data:CountFunction Caption="Count" />
</telerik:GridViewDataColumn.AggregateFunctions>
</telerik:GridViewDataColumn>
<telerik:GridViewDataColumn Header="Position" DataMemberBinding="{Binding Position}">
</telerik:GridViewDataColumn>
<telerik:GridViewDataColumn Header="Country" DataMemberBinding="{Binding Country}">
</telerik:GridViewDataColumn>
</telerik:RadGridView.Columns>

But then the aggragates are doubled initially and when I re-add the "number" column to the group by the aggregates are there only once but then the aggregate sorting buttons don't work(which makes sense since they are tied to the missing set of aggregates)

How do I make the aggregate sorting work with the aggregate defined in the column definition?
Tags
GridView
Asked by
tao
Top achievements
Rank 1
Answers by
Maya
Telerik team
Justin Wilson
Top achievements
Rank 1
Megan Vee
Top achievements
Rank 1
Pete
Top achievements
Rank 1
Share this question
or