Advertisement

Grouping data in a Silverlight DataGrid

I previously wrote about DataGrid grouping using the declarative model of adding GroupDescriptors.  Unfortunately that feature (the declarative part) never made it to the release of Silverlight 3.  It was pointed out to me that I should update that post and it has been on my //TODO list for a while.  Here’s an update…

First, I’m still using a sample data class of Person as my test data:

   1: using System.Collections.Generic;
   2:  
   3: namespace DataGridGroupingUpdated
   4: {
   5:     public class Person
   6:     {
   7:         public string FirstName { get; set; }
   8:         public string LastName { get; set; }
   9:         public string Gender { get; set; }
  10:         public string AgeGroup { get; set; }
  11:     }
  12:  
  13:     public class People
  14:     {
  15:         public static List<Person> GetPeople()
  16:         {
  17:             List<Person> peeps = new List<Person>();
  18:             peeps.Add(new Person() { FirstName = "Tim", LastName = "Heuer", Gender = "M", AgeGroup = "Adult" });
  19:             peeps.Add(new Person() { FirstName = "Lisa", LastName = "Heuer", Gender = "F", AgeGroup = "Adult" });
  20:             peeps.Add(new Person() { FirstName = "Zoe", LastName = "Heuer", Gender = "F", AgeGroup = "Kid" });
  21:             peeps.Add(new Person() { FirstName = "Zane", LastName = "Heuer", Gender = "M", AgeGroup = "Kid" });
  22:             return peeps;
  23:         }
  24:     }
  25: }

Then my XAML is a simple DataGrid (make sure to add assembly references to your project to System.Windows.Controls.Data):

   1: <UserControl x:Class="DataGridGroupingUpdated.MainPage"
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
   5:     xmlns:datacontrols="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"
   6:     mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
   7:     <Grid x:Name="LayoutRoot">
   8:         <StackPanel>
   9:             <StackPanel Orientation="Horizontal">
  10:                 <TextBlock Text="Group:" Margin="0,0,10,0" />
  11:                 <ComboBox x:Name="GroupNames" SelectionChanged="GroupNames_SelectionChanged">
  12:                     <ComboBox.Items>
  13:                         <ComboBoxItem Content="AgeGroup" IsSelected="True" />
  14:                         <ComboBoxItem Content="Gender" />
  15:                     </ComboBox.Items>
  16:                 </ComboBox>
  17:             </StackPanel>
  18:             <datacontrols:DataGrid x:Name="PeopleList" />
  19:         </StackPanel>
  20:     </Grid>
  21: </UserControl>

Notice the xmlns:datacontrols declaration at the top.

Now since we can’t do the grouping declaratively as in my previous sample with Silverlight 3 beta, here’s how we could do it.  In Silverlight 3 you have access to PagedCollectionView (add a reference to System.Windows.Data to get it).  This is a view that enables you to add sort and group descriptors.  In my initial loading code I instantiate a new PagedCollectionView passing in my List<Person> as the enumerable type.  I then set a default grouping on it.

   1: PagedCollectionView pcv = null;
   2:  
   3: public MainPage()
   4: {
   5:     InitializeComponent();
   6:     Loaded += new RoutedEventHandler(MainPage_Loaded);
   7: }
   8:  
   9: void MainPage_Loaded(object sender, RoutedEventArgs e)
  10: {
  11:     pcv = new PagedCollectionView(People.GetPeople());
  12:     pcv.GroupDescriptions.Add(new PropertyGroupDescription("AgeGroup"));
  13:  
  14:     PeopleList.ItemsSource = pcv;
  15: }

Then I can wire up a quick and dirty (just for demonstration purposes) ComboBox to show changing the grouping (or perhaps adding another one if you’d like):

   1: private void GroupNames_SelectionChanged(object sender, SelectionChangedEventArgs e)
   2: {
   3:     if (pcv != null)
   4:     {
   5:         // comment this next line out to see
   6:         // adding additional groupings.
   7:         pcv.GroupDescriptions.Clear();
   8:         ComboBoxItem itm = (ComboBoxItem)GroupNames.SelectedItem;
   9:         pcv.GroupDescriptions.Add(new PropertyGroupDescription(itm.Content.ToString()));
  10:     }
  11: }

You see we are just changing the PagedCollectionView and not the DataGrid.  The binding that exists between them already understands what to do – so we just have to change the data source, not the control displaying the source.  Put them all together and the running application shows the grouping:

DataGrid grouping sample image

Hopefully this helps clarify the change from SL3 beta and apologies for the delay in updating what is a common sample request.  Who knows, maybe in future versions the declarative model will come back :-).  Here’s the code for the above if you’d like to see it: DataGridGroupingUpdated.zip


This work is licensed under a Creative Commons Attribution By license.

  1. 11/4/2009 3:31 PM | # re: Grouping data in a Silverlight DataGrid
    I seriously need a way to change the text that appears in the grouping line. In your example, you didn't change the column headers, but if you did, giving the header "Type" for example, when we group by the column the grouping header is still "AgeGroup" instead of "Type".
    In my project, the class property names are highly technical, but I cannot change the grouping header. Do you have any plans to implement a solution?
    Maybe a new parameter in the initializer "new PropertyGroupDescription"...
  2. 11/4/2009 8:44 PM | # re: Grouping data in a Silverlight DataGrid
    That was impressive work. I always like your articles.
    OT:
    I have developed one application in silverlight and in that I am using DataGrid and there is one column for Image that is coming from Database. I have used Pager now whenever user navigate to another page, Image doesn't get refreshed. Could you please guide me?

    Thanks,
    Kishan
  3. 11/5/2009 5:18 AM | # re: Grouping data in a Silverlight DataGrid
    @Alan: I am trying to find a solution for this me too.

    If anyone has an answer on this please do share it with us
  4. 11/12/2009 9:24 AM | # re: Grouping data in a Silverlight DataGrid
    Hi, do you think there is an elegant way to catch the selected event on a header. I tried the SelectionChanged event but I dont know how to identify which header is selected, I just know its a header
  5. 11/16/2009 3:36 PM | # re: Grouping data in a Silverlight DataGrid
    @Alan & Antonis, would these Attributes help ?

    [System.ComponentModel.DataAnnotations.Required]
    [System.ComponentModel.DataAnnotations.Display(Name= "NewName", GroupName = "NewGroupName")]

    ?

    Rich

  6. 11/18/2009 1:13 PM | # re: Grouping data in a Silverlight DataGrid
    Thanks for shwoing how to do that. I am also interested to know if there is an easy way to display totals for certains columns in each group ?
  7. Gravatar
    11/18/2009 4:35 PM | # re: Grouping data in a Silverlight DataGrid
    Thanks for sharing the tip, very handy.
  8. 11/26/2009 12:54 PM | # re: Grouping data in a Silverlight DataGrid
    thanks admin
    Are you really cool
  9. 11/27/2009 2:02 PM | # re: Grouping data in a Silverlight DataGrid
    Is there any way to have a sum in the grouped row for specific columns? So if I were showing sales of a retail store by department I could sum together each of the entries inside the group to show a total for the group.

    Possible?
  10. Gravatar
    12/3/2009 7:52 PM | # re: Grouping data in a Silverlight DataGrid
    @Alan, you can change the template of the DataGridRowGroupHeader. See stackoverflow.com/.../silverlight-3-beta-datagr....
  11. 2/17/2010 5:37 PM | # re: Grouping data in a Silverlight DataGrid
    How can I change the name without using DataAnnotations? I don't want to have attributes on my classes just for this :@

  12. 2/17/2010 5:56 PM | # re: Grouping data in a Silverlight DataGrid
    I looked at the question in Stack Overflow and I thought that might help, but inside of the template we don't have information as of which is the selected group :( We get access to a "CollectionViewGroupInternal" instace, but it doesn't help to get the name of the group. However we could show information as adult/kid and the total (@Rick this would be what you need to format your sales totals). Anyway, withtout the information about the group name we wouldn't know if we're showing Age Group or Gender to tally it appropriately :(

    Has anyone find a way to do this?

 
Please add 4 and 1 and type the answer here:
First time here? You are looking at the most recent posts. You may also want to check out older archives. Please leave a comment, ask a question and consider subscribing to the latest posts via RSS or email. Thank you for visiting! (hide this)