RadDataGrid Aggregates in GroupBy when using a DataTable

0 Answers 104 Views
DataGrid
Clint
Top achievements
Rank 1
Iron
Iron
Clint asked on 26 Jun 2023, 04:37 PM

My application has several views with RadDataGrids populated by DataTables. Column Names for the RadDataGrid are taken from the DataTable.

I'm using the below code to have aggregate totals next to the GroupBy Headers and to also show the total number of records displayed in the Footer. This creates an empty Column in the grid. Hiding the column removes the totals from the footer.

Is there a better way of displaying totals with the GroupBy Headers? If the empty column is necessary, how do I hide it but keep the totals in the footer?

NOTE: PluginID is the first column in the DataTable for this particular view

        <telerik:RadDataGrid
            x:Name="dataGridPlugins"
            Grid.Row="4"
            Margin="0,10,0,0"
            ItemsSource="{Binding}"            
            ShowGroupHeaderAggregates="True"
            ShowColumnFooters="True" >
            <telerik:RadDataGrid.Columns>
                <telerik:DataGridTextColumn>
                    <telerik:DataGridTextColumn.AggregateDescriptors>
                        <telerik:PropertyAggregateDescriptor PropertyName="PluginID"
                                                             Function="Count"
                                                             Caption="Total:"/>
                    </telerik:DataGridTextColumn.AggregateDescriptors>
                </telerik:DataGridTextColumn>
            </telerik:RadDataGrid.Columns>
Maria
Telerik team
commented on 29 Jun 2023, 02:06 PM

Hеllo Clint,

The DataGrid exposes an Aggregates API through its DataGridColumn.AggregateDescriptors property where you can add PropertyAggregateDescriptors or DelegateAggregateDescriptors. The Telerik UI for .NET MAUI DataGrid Aggregates can be placed in the ColumnFooter as well as the GroupHeader and GroupFooter. The aggregates cannot create a column. You can refer to our documentation article about how to add columns in your DataGrid: .NET MAUI DataGrid Columns.

I am not sure what you mean by "better way of displaying totals with the GroupBy Headers". We have logged a feature request about an option to align aggregates in group header. If that is what you mean you could vote for the item in our public feedback portal. Here is the link: DataGrid: Add an option to align aggregates in group header.

If I don't understand you right can you please send an example project with current behavior, so I can see what is the case?

I am looking forward to your reply.

Regards,
Maria
Progress Telerik

Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.

Clint
Top achievements
Rank 1
Iron
Iron
commented on 29 Jun 2023, 05:03 PM

The problem is, the code I'm using adds an empty column to the grid. I can get aggregate totals into the GroupBy Header, but I don't see a way to do it without getting the blank column.

Given the following, which I'm using to display aggregates in the GroupBy Header, how would I reference a Column when my columns are being created by attaching a datatable:

            <telerik:RadDataGrid.Columns>
                <telerik:DataGridTextColumn>
                    <telerik:DataGridTextColumn.AggregateDescriptors>
                        <telerik:PropertyAggregateDescriptor PropertyName="PluginID"
                                                             Function="Count"
                                                             Caption="Total:"/>
                    </telerik:DataGridTextColumn.AggregateDescriptors>
                </telerik:DataGridTextColumn>

 

Here's a screenshot, this would be great except for the fact that I have an empty column:

 

Maria
Telerik team
commented on 04 Jul 2023, 01:59 PM

Hello Clint,

I tested the code snippet you sent. On my side, the code works as expected and the empty column is not added. I am missing something form the setup. Could you please send me a sample project, where I can test the behavior? 

I am looking forward to your reply.

Clint
Top achievements
Rank 1
Iron
Iron
commented on 04 Jul 2023, 03:49 PM

See attached zip with a sample page.
Maria
Telerik team
commented on 07 Jul 2023, 08:43 AM

Hello Clint, 

Thank you for the provided files.

I tested the project and understand what you have in mind. You don't need to add a new text column in the XAML file and add the aggregate to this column, because of this it appears as an empty column. Instead, you can set the aggregate to the first auto-generated column populated from the DataTable because you have set the AutoGenerateColumns property.

I hope this helps. Let me know if I can assist you further.

Clint
Top achievements
Rank 1
Iron
Iron
commented on 07 Jul 2023, 03:28 PM

That makes sense, I'm not seeing how to do that though. Is there some documentation or a sample somewhere showing how to do that?
Lance | Senior Manager Technical Support
Telerik team
commented on 07 Jul 2023, 04:01 PM

Hi Clint, the Columns property of the DataGrid is an ObservableCollection<DataGridColumn>. This means you can subscribe to the CollectionChanged event and then dynamically do what you want to that newly automatically generated added column.

Important note: Remember that the Columns collection must use the base type for column; DataGridColumn. So depending on what column property type you need to set, you may need to add additional logic to differentiate the column type.

Here's a simple example to help point you in the right direction.

public MainPage()
{
    InitializeComponent();

// subscribe to collectionChanged
    this.dataGrid.Columns.CollectionChanged += Columns_CollectionChanged;
}

Create your decision making logic in the CollectionChanged event handler:

private void Columns_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
    if (e.NewItems?.Count > 0)
    {
        var addedColumns = e.NewItems as IList<DataGridColumn>;

        foreach (var newColumn in addedColumns)
        {
            // if the property is available on the base 'DataGridColumn' type, then you can use it without differentiating the actual type
            // for example 'HeaderText' is available on every column type
            var headerText = newColumn.HeaderText;

            // Note
            // PropertyName does NOT exist on the base column type,
            // not available => var propName = newColumn.PropertyName <=
            // You can also check the column's type and write logic against that specific column type
            if (newColumn is DataGridTextColumn textColumn)
            {
                var propName = textColumn.PropertyName;

                if (propName == "MyPropertyIWantToAggregate")
                {
                    textColumn.AggregateDescriptors.Add(new PropertyAggregateDescriptor()
                    {
                        Caption = "sum",
                        Function = KnownFunction.Count,
                        PropertyName = propName
                    });
                }
            }

            // The same is true for other column types
            //if (newColumn is DataGridBooleanColumn boolColumn)
            //{
            //    var propName = boolColumn.PropertyName;
            //}

            //if (newColumn is DataGridComboBoxColumn comboColumn)
            //{
            //    var propName = comboColumn.PropertyName;
            //}
            
            //if (newColumn is DataGridNumericalColumn numericalColumn)
            //{
            //    var propName = numericalColumn.PropertyName;
            //}
        }
    }
}

You can find a list of all the column object types here => .NET MAUI DataGrid Documentation - Columns Overview.

Lance | Senior Manager Technical Support
Telerik team
commented on 07 Jul 2023, 04:30 PM

I just realized that MAUI uses a different paradigm for the CollectionChanged trigger, so a small tweak is needed to my last example code.

You need to check for the Reset action (instead of the a.AddedItems count), then you can iterate over the concrete columns to check for the type and add other things you want.

Here's an updated version of the event handler:

private void Columns_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
    //if (e.NewItems?.Count > 0) // not for MAUI DataGrid
    if(e.Action == NotifyCollectionChangedAction.Reset)
    {
        foreach (var column in this.dataGrid.Columns)
        {
            if (column is DataGridNumericalColumn { PropertyName: "Price" } numericalColumn)
            {
                numericalColumn.AggregateDescriptors.Add(new PropertyAggregateDescriptor
                {
                    Caption = "Total",
                    Function = KnownFunction.Sum,
                    PropertyName = numericalColumn.PropertyName
                });
            }
        }
    }
}

Note that I also changed the aggregate type and only use the NumericalColumn, this is just taking the opportunity to show you some more variants of checking/using specific column types

Clint
Top achievements
Rank 1
Iron
Iron
commented on 09 Jul 2023, 12:54 PM

Got it. I thought I was missing something in the XAML. I just tried this out and it worked greate. Thanks!

No answers yet. Maybe you can help?

Tags
DataGrid
Asked by
Clint
Top achievements
Rank 1
Iron
Iron
Share this question
or