Silverlight 4 – Datagrid (Sorting, Grouping, Filtering and Paging) – Tip of the day





0/5 (0 vote)
Datagrid (sorting, grouping, filtering and paging) in Silverlight 4
A Datagrid is an Excel like graphical user interface element that presents data in tabular format. It provides the ability to select, sort, group, filter, page, add, edit, delete from its associated data source.
In this article, I am going to discuss about the sorting, grouping, filtering and paging. Some of the features are built into Datagrid, say for example, sorting. But sometimes, we need to code them manually.
Before we start our journey, have a look at the diagram. If you understand the diagram, that’s good, if you don’t that’s even better. I will explain it as we proceed.
We can achieve the above functionalities in various ways (the hard way or the easy way). I am lazy and always looking for the easy way, so I prefer PagedCollectionView
class. It represents a view for sorting, grouping, filtering, paging.
Simply, I can say PagedCollectionView
is a collection view as a layer on top of a binding source collection that allows us to achieve the above functionalities without having to manipulating the underlying source. More easily, PagedCollectionView
is a wrapper for your collection.
PagedCollectionView
can act on any collection that implements the IEnumerable
interface such as a ObservableCollection
, List
, etc.
Sorting
Namespace: System.ComponentModel
Assembly: WindowsBase
(in WindowsBase.dll)
Sorting is the built in feature of the Datagrid and allows user to sort by clicking on the header of a column. But in our case, we will be sorting Datagrid based on the ComboBox
item selection.
SortDescriptions
collection of PagedCollectionView
describes how items are sorted in view. SortDescriptions
is a collection in which we can add more than one sort field. We add sort field by adding SortDescription
that specifies which property will be used for sorting and the direction (ascending or descending order).
The quick steps are listed below:
- Clear the existing sorting from the collection.
- Create a
SortDescription
and pass the name of the property to sort and direction. - Add the
SortDescription
to theSortDescriptions
collection. Based on the requirements, we can add more than oneSortDescription
(so it can be done multilevel).//============================================================== //Sort data by Fieldname private void SortByFieldName(string prmFieldName) { //globalPVC is a PagedCollectionView object if (globalPVC != null && prmFieldName.Trim().Length>0) { globalPVC.GroupDescriptions.Clear(); globalPVC.SortDescriptions.Clear(); globalPVC.SortDescriptions.Add(new SortDescription(prmFieldName.Trim(), ListSortDirection.Ascending)); } } //==================================================================================
Grouping
Namespace: System.Windows.Data
Assembly: PresentationFramework
(in PresentationFramework.dll)
Grouping is similar to sorting and can be done multilevel. For grouping, we are going to use PropertyGroupDescription
property.
GroupDescriptions
collection of PagedCollectionView
describes how items are grouped in view. GroupDescriptions
is collection in which we can add more than one Grouping. We add Grouping field by adding PropertyGroupDescription
that specify which property will be used for grouping.
The quick steps are listed below:
- Clear the existing grouping from the collection.
- Create a
PropertyGroupDescription
and pass the name of the property to group. - Add the
PropertyGroupDescription
to theGroupDescriptions
collection ofPagedCollectionView
. Based on the requirements, we can add more than onePropertyGroupDescription
(so it also can be done multilevel)://======================================================================= //Grouping data by Fieldname private void GroupByFieldName(string prmFieldName) { if (globalPVC != null && prmFieldName.Trim().Length>0) { //globalPVC is a PagedCollectionView object globalPVC.GroupDescriptions.Clear(); globalPVC.SortDescriptions.Clear(); globalPVC.GroupDescriptions.Add(new PropertyGroupDescription( prmFieldName.Trim())); } } //=========================================================================
Filtering
Namespace: System.Windows.Data
Assembly: System.Windows.Data
(in System.Windows.Data.dll)
Filtering is used to determine whether an item is suited for inclusion in the view. This can be achieved by setting a callback method to the PagedCollectionView.Filter
property.
Callback method provides the filtering logic. This callback method examines each row and indicates if the row should be included or excluded by returning true
or false
.
The quick steps are listed below:
- Remove the existing filter.
- Create a callback method that accepts a parameter of type
Object
. - Set the callback method to the
PagedCollectionView.Filter
property.//=============================================================================== void butFilter_Click(object sender, RoutedEventArgs e) { //globalPVC is a PagedCollectionView object globalPVC.Filter = null; globalPVC.Filter = new Predicate<object>(DoFilter); }
//Callback method private bool DoFilter(object o) { //it is not a case sensitive search Employee emp = o as Employee; if (emp != null) { if( emp.Name.ToLower().IndexOf (txtFilter.Text.Trim().ToLower()) >= 0 ) { return true; } else { return false; } } return false; } //===========================================================================
Paging
PagedCollectionView
is able to split data into multiple pages having a fixed number of rows per page. Paging is useful for large amount of data.
In Silverlight, paging became simpler because of DataPager
control. The DataPager
control provides a configurable user interface for paging through a data collection. We can bind the DataPager
to any IEnumerable
collection. In our case, we will bind DataPager
with PagedCollectionView
or ItemsSource
of the Datagrid
.
The following are the important properties from the data binding point of view:
PageSize
– Number of rows to be displayed per pageDisplayMode
– Defines the look of theDataPager
Source
–PagedCollectionView
or any collection that implementsIEnumerable
. You can modify the appearance of theDataPager
by setting theDisplayMode
property
Image source: http://msdn.microsoft.com/en-us/library/system.windows.controls.datapager(v=VS.95).aspx
Now we will develop a small project which will target the above features. The end result will resemble the following one. This is not a fancy one, but will serve our purpose.
Step 1
Create a new Silverlight application project and name it whatever you like.
Step 2
First focus on the UI build. Open the MainPage.xaml and place the following code between UserControl
tag. Now your XAML should be similar to the following:
<Grid x:Name="LayoutRoot" Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="25" />
<RowDefinition Height="25" />
<RowDefinition Height="25" />
<RowDefinition Height="25" />
<RowDefinition Height="227" />
<RowDefinition Height="25" />
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Left" Grid.Row="0">
<TextBlock Name="textBlock1" VerticalAlignment="Top" Text="Sort By:"
Height="20" Width="100" />
<ComboBox Name="comSort" VerticalAlignment="Top"
Width="330" />
</StackPanel>
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Left" Grid.Row="1">
<TextBlock Name="textBlock3" VerticalAlignment="Top" Text="Group By:"
Width="100" />
<ComboBox Name="comGroup" VerticalAlignment="Top"
Height="20" Width="330" />
</StackPanel>
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Left" Grid.Row="2">
<TextBlock Name="textBlock4"
VerticalAlignment="Top" Text="Search by name :"
Width="100" />
<TextBox Name="txtFilter" Width="330"/>
<Button Name="butFilter" Content="Search" Width="50" />
</StackPanel>
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Left" Grid.Row="3">
<TextBlock Name="textBlock5"
VerticalAlignment="Top" Text="Enable Pagin"
Width="100" />
<CheckBox x:Name="chkPaging" />
</StackPanel>
<sdk:DataGrid x:Name="dgEmployee" AutoGenerateColumns="True"
Grid.Row="4" Height="211" Margin="0,16,0,0"
VerticalAlignment="Top" Width="453"
HorizontalAlignment="Left" />
<sdk:DataPager x:Name="pagerEmployee" PageSize="3"
DisplayMode="PreviousNext"
NumericButtonCount="3" Grid.Row="5"
Height="24" HorizontalAlignment="Left"
VerticalAlignment="Center" Margin="0,0,147,0" Width="450"
Visibility="Collapsed"></sdk:DataPager>
</Grid>
Step 3
In order to keep the project simple, we will work on in memory data (a future article will work on real data from database). So at this stage, we are going to create and code an Employee
class. The following is the Employee
class:
public class Employee
{
public int EmployeeID { get; set; }
public string Name { get; set; }
public string Department { get; set; }
public double Salary { get; set; }
}
Step 4
Now the code behind:
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.ComponentModel;
using System.Collections.ObjectModel;
namespace FirstDataGridC
{
public partial class MainPage : UserControl
{
PagedCollectionView globalPVC;
public MainPage()
{
InitializeComponent();
//Populate Sort and Group Combo
PopulateCombos();
//Load Employee and Populate Datagrid
LoadEmployee();
//Selection Changed Event for Sort and Group Combo
comSort.SelectionChanged += new SelectionChangedEventHandler(
comSort_SelectionChanged);
comGroup.SelectionChanged += new SelectionChangedEventHandler(
comGroup_SelectionChanged);
//Click Event Handler
butFilter.Click += new RoutedEventHandler(butFilter_Click);
chkPaging.Click += new RoutedEventHandler(chkPaging_Click);
}
void chkPaging_Click(object sender, RoutedEventArgs e)
{
if (chkPaging.IsChecked == true)
{
//avtivate datapager
//pagerEmployee.Source = globalPVC;
pagerEmployee.Source = dgEmployee.ItemsSource;
pagerEmployee.Visibility = Visibility.Visible;
}
else {
//deactivate datapager
pagerEmployee.Source = null;
pagerEmployee.Visibility = Visibility.Collapsed ;
LoadEmployee();
}
}
void butFilter_Click(object sender, RoutedEventArgs e)
{
globalPVC.Filter = null;
globalPVC.Filter = new Predicate<object>(DoFilter);
}
//Callback method
private bool DoFilter(object o)
{
//it is not a case sensitive search
Employee emp = o as Employee;
if (emp != null)
{
if( emp.Name.ToLower().IndexOf (txtFilter.Text.Trim().ToLower()) >= 0 )
{
return true;
}
else
{
return false;
}
}
return false;
}
void comGroup_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
string localItem = comGroup.SelectedItem as string;
GroupByFieldName(localItem);
}
//Grouping data by Fieldname
private void GroupByFieldName(string prmFieldName)
{
if (globalPVC != null && prmFieldName.Trim().Length>0)
{
globalPVC.GroupDescriptions.Clear();
globalPVC.SortDescriptions.Clear();
globalPVC.GroupDescriptions.Add(new PropertyGroupDescription(
prmFieldName.Trim()));
}
}
void comSort_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
string localItem = comSort.SelectedItem as string;
SortByFieldName(localItem.Trim());
}
//Sort data by Fieldname
private void SortByFieldName(string prmFieldName)
{
if (globalPVC != null && prmFieldName.Trim().Length>0)
{
globalPVC.GroupDescriptions.Clear();
globalPVC.SortDescriptions.Clear();
globalPVC.SortDescriptions.Add(new SortDescription(prmFieldName.Trim(),
ListSortDirection.Ascending));
}
}
//Loading dummy data
private void LoadEmployee()
{
ObservableCollection<Employee> objColEmp =
new ObservableCollection<Employee>();
objColEmp.Add(new Employee { EmployeeID = 1,
Name = "Sumon Barua", Department = "IT", Salary = 10 });
objColEmp.Add(new Employee { EmployeeID = 2, Name = "Sharmila Barua",
Department = "Finance", Salary = 11 });
objColEmp.Add(new Employee { EmployeeID = 3, Name = "Sujan Barua",
Department = "IT", Salary = 8 });
objColEmp.Add(new Employee { EmployeeID = 4, Name = "Saurov Barua",
Department = "Finance", Salary = 8 });
objColEmp.Add(new Employee { EmployeeID = 5, Name = "Raj1",
Department = "IT", Salary = 20 });
objColEmp.Add(new Employee { EmployeeID = 6, Name = "Raj2",
Department = "IT", Salary = 25 });
objColEmp.Add(new Employee { EmployeeID = 7, Name = "Raj3",
Department = "IT", Salary = 8 });
globalPVC = new PagedCollectionView(objColEmp);
dgEmployee.ItemsSource = globalPVC;
}
//Populating ComboBox
private void PopulateCombos()
{
comSort.Items.Add("----- Select a field name -----");
comSort.Items.Add("Name");
comSort.Items.Add("Department");
comSort.Items.Add("Salary");
comSort.SelectedIndex = 0;
comGroup.Items.Add("-----Select a field name -----");
comGroup.Items.Add("Name");
comGroup.Items.Add("Department");
comGroup.Items.Add("Salary");
comGroup.SelectedIndex = 0;
}
}
}
To top it all, I hope this basic introduction of Datagrid
gave you a basic insight and hopefully you can use it to your advantage.
Happy coding!