Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Grouping Records in Silverlight DataGrid using PagedCollectionView

0.00/5 (No votes)
7 Dec 2010 1  
Do you work with Silverlight DataGrid and want to group your records inside the DataGrid in a proper manner? If so, this article is for you. Here we will learn about data grouping inside a DataGrid.

Introduction

Do you work with Silverlight DataGrid and want to group your records inside the DataGrid in a proper manner? If so, this article is for you. Here, we will learn about data grouping inside a DataGrid. In this article, we will learn how to group data inside a Grid. We will discuss all these step-by-step and with proper images, so that, you can understand it very easily. The full source code has been attached. You can freely download it and that will be more helpful for you to understand. Read the complete article to learn it.

Background

Sometimes you need to group your data by column name inside a Silverlight DataGrid. You may need grouping in multiple layers. To do this, what will you do? There is a CLR class for you to do this, named “PagedCollectionView”. This class will do all those things for you, if you know what to do and how to do it.

image

The above screenshot is a sample of what we want to implement here. This article is for you to understand the functionality and the way to implement this feature in your DataGrid control. You don’t have to write a huge code, but only a little code to do this. Let us start describing the code.

Implementing the Basic DataGrid with Records

Before doing any data grouping, we need to create our XAML page which will have a DataGrid binded to a collection present in the ViewModel. I know this is very simple for you. For our example, we will create a Model “Employee” with some basic properties like “Firstname”, “Lastname”, “Age”, “City”, etc. as shown in the above screenshot. Then we will create a ServiceProvider to return a collection of Employees. Now, we need to implement our ViewModel. Create a property which will hold a collection of Employee. It will be an ObservableCollection of type Employee. Inside the constructor, we will call the EmployeeProviders to get the collection of Employee. That’s all about the ViewModel. If you don’t want, you can skip the provider too. But in that case, you have to manually populate the records inside the ViewModel. Let’s see the plain code of ViewModel, which we implemented just now:

using System.Collections.ObjectModel;
using System.ComponentModel;
using DataGridDemo1.Models;
using DataGridDemo1.Providers;
 
namespace DataGridDemo1.ViewModels
{
public class MainViewModel : INotifyPropertyChanged
{
private ObservableCollection<Employee> employees;
public ObservableCollection<Employee> Employees
{
get { return employees; }
set
{
employees = value;
OnPropertyChanged("Employees");
}
}
 
public MainViewModel()
{
// Fetch the Employee Details from provider and set to Employees collection
Employees = EmployeeProviders.GetEmployeeDetails();
}
 
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}

Come to the XAML page. Here we will set the ItemsSource of the DataGrid to the Employees collection property present in the ViewModel. Here is the code:

<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:viewModels="clr-namespace:DataGridDemo1.ViewModels"
xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" 
x:Class="DataGridDemo1.Views.MainView">
<UserControl.Resources>
<viewModels:MainViewModel x:Key="MainViewModel"/>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White">        
<sdk:DataGrid 
IsReadOnly="True" Margin="10,40,10,10"
ItemsSource="{Binding Employees, Source={StaticResource MainViewModel}}"/>
</Grid>
</UserControl>

Our basic DataGrid is ready with records. If you run the application now, you will see that the application has Data records with all the fields. You will not see any advanced feature there except the basic sorting one.

image

The above image is a screenshot of what we implemented as of now. The whole application source code is available to download. If you are facing any issue, you can try downloading that.

PagedCollectionView to Extend Feature

PagedCollectionView represents a view for grouping, sorting, filtering, and navigating a paged data collection, which comes under the System.Windows.Data.dll assembly. Here is a list of Methods, Events and Properties present inside PagedCollectionView. You can use them easily.

alt

Go through all the properties and methods from the Visual Studio Object explorer. Here we will discuss on the grouping functionality of the DataGrid records using this class.

Implementing Grouping using PagedCollectionView

Let us implement the grouping as simply as possible. Open your ViewModel and change the property type of the Employees collection. Earlier we used type of ObservableCollection<Employee> and now just change it to type PagedCollectionView. Here is the screenshot of what you have to do:

image

Now, it’s turn for the providers. We are getting the collection from the EmployeeProvider as ObservableCollection of type Employee. So, in the ViewModel, instead of directly storing in the property, convert it to a PagedCollectionView. Our property also expects the same type. To do this, create a new instance of PagedCollectionView by passing the entire collection of employees to the constructor. The class implementation will handle this for you.

image

Once this conversion is done, run your application. It will run successfully without any error. If you get any error, fix it. In the application, you will not see any difference as we didn’t implement the functionality. We just converted the collection type to a different one. Create a new public method in view model to implement the same. Inside the method, first of all clear the GroupDescriptions of the collection of PagedCollectionView.

public void GroupDataByColumnName(string groupName)
{
Employees.GroupDescriptions.Clear();
Employees.GroupDescriptions.Add(new PropertyGroupDescription(groupName));
}

Then add a new group description with the name of the column that you want to group. The above code will group the data based on the parameter that we will pass to GroupDataByColumnName() and if you want to do multiple level of grouping, you have to add two or more group descriptions to the PagedCollectionView. For our case, we will modify our XAML page with a ComboBox which will have the group name, i.e., column name of the DataGrid. Here is the fill XAML for your reference:

<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:viewModels="clr-namespace:DataGridDemo1.ViewModels"
xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" 
x:Class="DataGridDemo1.Views.MainView">
<UserControl.Resources>
<viewModels:MainViewModel x:Key="MainViewModel"/>
</UserControl.Resources>
<StackPanel x:Name="LayoutRoot" Background="White"
DataContext="{StaticResource MainViewModel}">
<ComboBox Width="200" Height="20" Margin="10"
HorizontalAlignment="Left" SelectionChanged="ComboBox_SelectionChanged">
<ComboBoxItem Content="City"/>
<ComboBoxItem Content="State"/>
<ComboBoxItem Content="Department"/>
</ComboBox>
<sdk:DataGrid 
IsReadOnly="True" Margin="10" ItemsSource="{Binding Employees}"/>
</StackPanel>
</UserControl>

From the above XAML code, you can easily understand what we did there. Implement the Selection Changed event for the ComboBox and retrieve the group name. Pass it to the viewmodel method to do the grouping. Here is the code behind code to understand the implementation:

private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var selectedItem = ((sender as ComboBox).SelectedItem as ComboBoxItem);
var groupName = selectedItem.Content.ToString();
 
(Resources["MainViewModel"] as MainViewModel).GroupDataByColumnName(groupName);
}

Once all the implementation is over, we will be able to run our application.

See it in Action

It’s time for us to run the application. You will see the same UI and one ComboBox with addition to that. Click the combobox to drop down the list of group names.

image

Select any group name from the drop down and you will see that the DataGrid record has been grouped properly with the same group name.

image

Change to a different group name and you will see the grouping has been changed automatically at runtime. No additional code to do this implementation. PagedCollectionView does everything for you.

image

image

If you try to sort the DataGrid record, you will notice that the records will sort with respect to the group. See the below screenshot. Here we grouped the records for “Department”. Now sorting on “Age” applies to the group department. The records will sort as per the department.

image

If you want to sort in descending order, then also it will sort with respect to the grouped department name. View the below image to check it.

image

You can see that all the things are working perfectly for us by using the PagedCollectionView. It’s a Silverlight compliant class and you can use it whenever required as per your need. Do you need the full code for ViewModel? Ok, here it is:

using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Data;
using DataGridDemo1.Providers;
 
namespace DataGridDemo1.ViewModels
{
public class MainViewModel : INotifyPropertyChanged
{
private PagedCollectionView employees;
public PagedCollectionView Employees
{
get { return employees; }
set
{
employees = value;
OnPropertyChanged("Employees");
}
}
 
public MainViewModel()
{
// Fetch the Employee Details from provider and set to Employees collection
Employees = new PagedCollectionView(EmployeeProviders.GetEmployeeDetails());
}
 
public void GroupDataByColumnName(string groupName)
{
Employees.GroupDescriptions.Clear();
Employees.GroupDescriptions.Add(new PropertyGroupDescription(groupName));
}
 
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}

The whole source code is available here to download as a zip. If you want, you can download it separately and check the implementation code directly inside your Visual Studio IDE.

Further Reading

End Note

You can see that it is very simple to implement if you know about the class and the implementation process. Once you know about this, it is very simple for you to implement. More will come on this topic. For now, experiment on the other features of the same collection view. I will post more shortly. Enjoy reading my articles. Last but not least, I need your feedback/suggestion to improve all of my articles. Don’t forget to write a line on the same. If you have any queries, please use the same forum. I will try to answer your queries as soon as possible.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here