Silverlight 4 DataGrid Filtering using DataGridColumnStyle

In Silverlight 4, the DataGrid control provides many features for effective data representation. I must say that most of the end-user’s requirements for Tabular Data representation and interaction can be easily accomplished using the DataGrid control. Let’s consider a scenario where the end-user is working on a Silverlight application where the data is displayed using DataGrid and he wants to filter the data in the column using some control in the Row Header, something similar to that in Microsoft Excel.

To provide such a  functionality in the SL DataGrid, we can make use of the DataGridColumnHeader and apply a style on it. This is possible because the DataGrid control has the separate programmable objects like DataGridCell, DataGridRow etc. using which customization on the DataGrid becomes very easy. Follow these steps:

Step 1: Create a Silverlight application, and add the following classes in it

Silverlight DataGrid Source
The above classes define the Employee Entity type and the Employee Collection type for DataBinding with UI.

Step 2: Open MainPage.Xaml and write the following XAML (Note:Please Drag-Drop DataGrid)

image

The above XAML code has the following important features:
  • The DataGrid defines columns which are bound with the public properties declared in the Employee class.
  • The UserControl resources defines Style which is Targeted to DataGridColumnHeader. The style is defined for the Template property of the DataGridColumnHeader. This Template further defines ControlTemplate which is configured to display TextBox in the DataGridColumnHeader. This TextBox subscribe to the TextChanged event which is implemented in the code-behind.
  • The XAML define two CheckBoxes which subscribe to the Click event.
Step 3: Open MainPage.Xaml.cs and write the following code:

using System.Linq;
using System.Windows;
using System.Windows.Controls;

namespace SL4_DataGrid_Column_Sum_and_Grouping
{
    public partial class MainPage_ColumnHeader : UserControl
    {
        EmployeeCollection EmpCol;

        //Boolean variables for filtering conditions. The value of this will be set in Click event of the CheckBoxes.
        bool IsEmpNameFilter = false;
        bool IsDeptNameFilter = false;


        public MainPage_ColumnHeader()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Method for Binding the Initial Data with The DataGrid
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            EmpCol = new EmployeeCollection();
            dgEmp.ItemsSource = EmpCol;
        }

        /// <summary>
        /// The ChekcBox click for EmpName Column.
        /// When Clicked and Checked, the DataGridColumnHeader will show the TextBox
        /// User now type values in this TextBox to filter the EmpName Column Values
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void chkEmpName_Click(object sender, RoutedEventArgs e)
        {
            DataGridColumn Dc = dgEmp.Columns[1];
            bool? Selected = chkEmpName.IsChecked;
            if (Selected == true)
            {
                Style sty = this.Resources["dgHeaderStyle"] as Style;
                Dc.HeaderStyle = sty;
                IsEmpNameFilter = true;
            }
            else
            {
                Dc.HeaderStyle = null;
                dgEmp.ItemsSource = EmpCol;
            }
        }
        /// <summary>
        /// The ChekcBox click for DeptName Column.
        /// When Clicked and Checked, the DataGridColumnHeader will show the TextBox
        /// User now type values in this TextBox to filter the DeptName Column Values
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void chkDeptName_Click(object sender, RoutedEventArgs e)
        {
            DataGridColumn Dc = dgEmp.Columns[2];
            bool? Selected = chkDeptName.IsChecked;
             if (Selected == true)
             {
                
                 Style sty = this.Resources["dgHeaderStyle"] as Style;
                 Dc.HeaderStyle = sty;
                 IsDeptNameFilter = true;
             }
             else
             {
                 Dc.HeaderStyle = null;
                 dgEmp.ItemsSource = EmpCol;
             }
        }

        
        /// <summary>
        /// This method will filter the collection based upon the the Boolean
        /// value. The filter will be either on the EmpName column or on DeptName
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void txtFilter_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (IsEmpNameFilter)
            {
                var Res = from Emp in EmpCol
                          where Emp.EmpName.StartsWith((sender as TextBox).Text)
                          select Emp;
                dgEmp.ItemsSource = Res;
            }
            if (IsDeptNameFilter)
            {
                var Res = from Emp in EmpCol
                          where Emp.DeptName.StartsWith((sender as TextBox).Text)
                          select Emp;
                dgEmp.ItemsSource = Res;
            }
        }
    }
}


 

Every method in the above class has self-explanatory comments. The Style defined in the XAML is accessed in the code-behind and is applied when the CheckBox is checked. This style will display TextBox in the specific column header. In this case, ‘EmpName’ and ‘DeptName’ columns are used. Once the textbox is displayed, if the end-user types the text in it, the DataGrid will show the data as per the filer from the ‘EmpCol’ collection.
Step 4: Run the application:
Silverlight DataGrid Filter

Click on the EmpName CheckBox and the ‘EmpName’ header will be replaced by the TextBox. Type the Filter string in it and you shpuld see the following result:

Silverlight DataGrid Filter

Repeat the same for the DeptName column as well.

Download the source code




About The Author

Mahesh Sabnis is a Microsoft MVP having over 18 years of experience in IT education and development. He is a Microsoft Certified Trainer (MCT) since 2005 and has conducted various Corporate Training programs for .NET Technologies (all versions). He also blogs regularly at DotNetCurry.com. Follow him on twitter @maheshdotnet

4 comments:

Anonymous said...

very very nice. Thanks a lot!

Suprotim Agarwal said...

Nice article Mahesh! Have you tested this against a large set of rows - say 10K-20K or even more?

josefer said...

Very good, how would you do it to filter by both columns at the same time.

Anonymous said...

Hi Friend

Very is download link
Actually "download source code" is not hyper-linked.

Kanthesha Murthy