Click here to Skip to main content
15,879,348 members
Articles / All Topics

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

Rate me:
Please Sign up or sign in to vote.
4.93/5 (12 votes)
28 May 2010CPOL4 min read 124.7K   32   7
A Datagrid is an excel like graphical user interface element that presents data in tabular format. It provides the ability to select, sorting, grouping, filtering, paging, adding, editing, deleting from its associated data source.

A Datagrid is an excel like graphical user interface element that presents data in tabular format. It provides the ability to select, sorting, grouping, filtering, paging, adding, editing, deleting 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 them as we proceed.

SilverlightDatagrid

We can achieve above functionalities in various way(hard way or 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 ObservableCorllection, 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 specify which property will be used for sorting and the direction(ascending or descending order).

The Quick Steps

  1. Clear the existing sorting from the collection.
  2. Create a SortDescription and pass the name of the property to sort and direction
  3. Add the SortDescription to the SortDescriptions collection. Based on the requirements we can add more than one SortDescription(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 groping.

The Quick Steps

  1. Clear the existing grouping from the collection.
  2. Create a PropertyGroupDescription and pass the name of the property to group.
  3. Add the PropertyGroupDescription to the GroupDescriptions collection of PagedCollectionView. Based on the requirements we can add more than one PropertyGroupDescription (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

  1. Remove the existing filter.
  2. Create a callback method that accepts a parameter of type Object.
  3. 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 page
  • DisplayMode - Defines the look of the DataPager
  • Source - PagedCollectionView or any collection that implements IEnumerable

You can modify the appearance of the DataPager by setting the DisplayMode property 

untitled

 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 to the following one. This is not a fancy one but will serve our purpose.

   grid

 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(in 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 {
                //deavtivate 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 at all, I hope this basic introduction of Datagrid gave you a basic insight and hopefully you can use it to your advantage.

Happy coding.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Lavender
Australia Australia
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralPageCollectionView and DataGrid combindly hits performance. Pin
vrunda bhatt21-Mar-11 20:59
vrunda bhatt21-Mar-11 20:59 
GeneralRe: PageCollectionView and DataGrid combindly hits performance. Pin
Neovegeto25-Oct-11 14:46
Neovegeto25-Oct-11 14:46 
QuestionCan we change the style of the Group Header? Pin
Kunal Chowdhury «IN»30-Nov-10 19:13
professionalKunal Chowdhury «IN»30-Nov-10 19:13 
GeneralThank for the excellent code, one slight improvement. Pin
Wayne B20-Aug-10 10:51
Wayne B20-Aug-10 10:51 
GeneralMy vote of 5 Pin
SusantaG14-Aug-10 1:26
SusantaG14-Aug-10 1:26 
Generalthanks for article Pin
sharadcs0528-Jul-10 3:55
sharadcs0528-Jul-10 3:55 
GeneralStraight to the point Pin
Sammi200128-May-10 16:27
Sammi200128-May-10 16:27 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.