Summary rows in Datagrid with multiple groups

Sometime back I posted one way to show the Summary/Totals in the group header and be able to resize individual columns when the columns are resized. That method has a limitation of not supporting nested groups. we can extend the same method to support multiple groups

Here are the steps.
we will start with what we had like in the previous sample.
1. we will add 1 GroupHeader style for each group we have. In my sample all the GroupHeader styles are same. One important change is there is a stackpanel in the GroupHeader named “ghsp” which hosts all the columns in the GroupHeader. we will add a Tag attribute and give a value of  “n-1” when  “n” is the number of groups in the datagrid. if you have 3 groups then there will be 3 group header styles and Tag attribute  will be 2, 1, 0. This is how we can differentiate the different level group headers

2. The next change is in the Resize method. ” * 20″ is for resizing the column with groupname in the group header, 20 is roughly the size of indentation for each group (could be different if you change defaults in the template)

void Resize()
        {
            headers = datagrid1.GetChildrenByType<StackPanel>().Where(x => x.Name == “ghsp”).ToList();
            headers.ForEach(x =>
            {                
               (x.Children[0] as DataGridCell).Width = dghc.Children[1].RenderSize.Width + (Int32.Parse(x.Tag.ToString()) * 20) ;

                for (int i = 2; i < dghc.Children.Count – 2; i++)                                   
                    (x.Children[i – 1] as DataGridCell).Width = dghc.Children[i].RenderSize.Width;
               
            });
          
        }

3.  In the converter we have to change the way we get the totals from the CollectionViewGroup

private decimal GetProductTotal(CollectionViewGroup cvg)
        {
            decimal total = 0;
            int counter = 0;
            while (counter < cvg.Items.Count)
            {
                if (cvg.Items[counter] is CollectionViewGroup)
                    total += GetProductTotal(cvg.Items[counter] as CollectionViewGroup);
                else
                    total = (cvg.Items as IEnumerable<object>).Sum(x => (x as Product).Total);

                counter++;
            }
            return total;
        }

you can download the code from here

26 thoughts on “Summary rows in Datagrid with multiple groups

  1. Hi Lee,

    Thanks for the great article. It helped me to meet some of the requirements in my project.

    Regards
    Arun

  2. Hi Lee,
    Great post, I got one problem though, when I update the itemsource and rebind the datagrid, I get wrong resizing of the row group headers, any thoughts?

    1. Hi,
      If you resized the headers before the update, they wont be preserved after you rebind the datagrid. is it working correctly the first time. if it is working correctly the first time and not after you rebind, may be you have to force a layout update or something.

  3. Yeah it is working fine first time, but as soon as the datagrid is rebound it goes pear shape. I’m calling UpdateLayout on the datagrid after rebinding but still no luck

  4. Hi,
    I have just tested that solution and works fine but I’m still have a problem with row group headers. I get wrong size:(. I’m binding data from wcf service and when the method is completed I bind all e.result to grid. Then I call method updateLayout but it is not working correctly. Any suggestions?

      1. Hi,
        looks like your column widths are right but not offset correctly. can you check the resize function code. look at #2. in the post

  5. I’ve checked this method; now looks like this
    void Resize()
    {
    headers = datagrid1.GetChildrenByType().Where(x => x.Name == “ghsp”).ToList();
    headers.ForEach(x =>
    {
    (x.Children[0] as DataGridCell).Width = dghc.Children[1].RenderSize.Width + (Int32.Parse(x.Tag.ToString())*10);

    for (int i = 2; i < dghc.Children.Count – 2; i++)
    (x.Children[i – 1] as DataGridCell).Width = dghc.Children[i].RenderSize.Width;

    });

    }

    I've changed size to 10 and my first level header group now is ok but still I can't find width to my second level group header

  6. now I set :)….
    and works fine:)
    sorry I’ve forgot about “0” value

    thanks a lot for helping me and patience:)

    Greetings
    JS

  7. Hi,
    I’ve got another problem :). I’m trying to rebind my grid after inserting data. When I’m calling BindGridGener() method in void webClient_InsertCompleted(object sender, ServiceReference.InsertCompletedEventArgs e) this not working at all.

  8. Thanks for reply
    “What does it mean when you say not working at all.”

    First time when I loading page my grid binding. Then when I inserted data I’m trying to rebind grid.I’m calling those method:
    void webClient_InsertCompleted(object sender, ServiceReference.InsertCompletedEventArgs e)
    {
    bool result = Convert.ToBoolean(e.Result);
    if (result)
    {
    BindGridGener();

    }
    }
    and application is getting stuck.

  9. Hi, it’s me again 🙂
    Now i have problem with refreshUI method.

    When i set height to auto in my datagrid, and number of records is bigger than 200 (about), than IE/GoogleChrome/Firefox increase memory usage to 200 MB and CPU to 60% and in the end Silverlight plugin go to crash.

    When height of datagrid is set absolute (for example to 700), there is everything ok, even with 1700 records in datagrid.

    I think this is a probelm with refreshUI or with converter. To many recursion method ?

    There is any way to fix this problem ? Or any way to speed up refreshUI method ?

  10. Hello!
    Great thanks for this and previous posts. Without them, I would never achieve what I wanted.
    But there’s a problem anyway.
    When you click expend or collapse the group, it takes some time to refresh.
    I fear that if my app will have thousands of records, it will be much too slow (though it is a bit slow already with a dozen of records).
    Any ideas on improving this issue?

  11. By the way, just noticed that the problem affects not only expanding the group, but anything that deals with the datagrid – for example, scrolling it.

    1. Hi,
      There is always a problem with the datagrid with large number of rows. Try to reduce the number of rows that are shown in the datagrid.

  12. Hi Lee,
    Thanks for this excellent article, it helped me a lot, just struggling with one thing, because my datagrid contains more no. of columns I’m getting a horizontal scroll bar but the Grouprowheader is not moving when the horizontal scroll bar is moved, please give me some pointer to correct this issue.

  13. Lee,
    By using I’m able to scroll the grouprowheader as well now. But still strugguling to get the first grouprowheader column alone to be frozen just like my datagrid row’s first column frozen.

  14. I pasted the AreRowGroupHeadersFrozen datagrid element example in my previous post, I think the system has removed the tag automatically hence this post.

    1. Hi,
      I have seen comments about things not working properly, when there are frozen columns. I could not find a solution for that.

  15. Hi
    That is a greate Article. but what a bout horizontal scrollbar. i have 9 summary column group and it might have a better visualization if i could enable horizontal scroll bar.
    any help ;(

Leave a reply to lee Cancel reply