Creating WPF Filterable Data Grid Using C# Code Behind

Introduction

This article provides a detailed introduction to the develop of a custom WPF DataGrid. This custom DataGrid is inherited from the base control "System.Windoes.Controls.DataGrid". It contains one public property named "IsFilter" that enables the DataGrid to be filterable.

Properties

The properties of the Custom DataGrid are:

  1. DataList
  2. SearchValue
  3. ColumnName
  4. IsFilter

DataList: This property is the object of ICollectionView. The IcollectionView interface belongs to "System.ComponentModel". It's most powerfull feature is, it enables collections to have the functionality of current record management, custom sorting, filtering and grouping. The DataList Property contains an items list bound with a DataGrid and passes it as an items source of the base DataGrid.

SearchValue: It is the private property whose value will be searched in the Data Grid. The data type is Object.

ColumnName: It is also a private property and is a column name of the Custome Data Grid whose cell value will be searched. The data type is string.

IsFilter: Boolean data type, enables the DataGrid to be filterable.

This DataGird contains one private function named "CustomFilter" that filters the (ItemsSource) ICollectionView of the custom DataGrid based on the search value. It takes items of the collection as a parameter.

private bool CustomeFilter(object item)

{

    Type TP = item.GetType();

    PropertyInfo PI = TP.GetProperty(this.ColumnName);

    string values = PI.GetValue(item).ToString();

    values = values.ToUpper();

    return values.StartsWith(this.SearchValue.ToString().ToUpper());

}
 
Two functions (OnInitialized and OnItemsSourceChanged) are overridden by this custom data grid from the base Data Grid to make some custom action such as binding and displaying custom controls in the header of each column of the custom DataGrid.

Override Functions

  1. OnInitialized
  2. OnItemsSourceChanged

OnInitialized: In this function I have only initialized the custom properties.

OnItemSourceChanged: In this function, templates are added in to the header of each column of the custom DataGrid such as TextBox or CheckBox control. If the data type of the column is DagaGridTextColumn then the TextBox will be added into the header or the data type of the column is DataGridCheckBoxColumn then the CheckBox will be added to the header.

Use the following procedure to develop the custom filterable Data Grid.

1. Open your Visual Studio, in the start page click on the New Project Link, select the Class Library template from the templates window then rename the project to CustomeControl and class1 to FilterableDataGrid.

2. Declare three properties(DataList,SearchValue, ColumnName and IsFilter), the code is given below:

private ICollectionView DataList { get; set; }

private object SearchValue { get; set; }

public string ColumnName { get; set; }

public bool IsFilter { get; set; }

3. Inherit the class from "System.Windows.Controls.DataGrid" and override the oninitialized and onitemSourceChanged functions.

4. In the oninitialized function initialize all the properties declared in the class level as in the following:

base.OnInitialized(e);

this.DataList = null;

this.SearchValue = null;

this.ColumnName = "";

this.IsFilter = false;
 
5. In the onItemSourceChanged function don't pass the new item source to the base OnItems Source Changed function, first pass is to the DataList then pass the DataList to the base OnItemsSourceChanged.

6. DataList = CollectionViewSource.GetDefaultView(newValue);

7. Then check the IsFilter property for true, if it is true then using the loop set the header template of each column of the DataGrid. If the Column Type is "DataGridTextBoxColumn" then add text box to the header template otherwise if the column type is "CheckBoxColumn" then add a checkbox to the header template.

8. Use the "ElementFrameworkFactory" Class to add a template to the column header and set the required properties such as name, events and so on. I have added the following values to the properties; see the following code:

Note: the following is code in the OnitemSourceChanged function.

DataList = CollectionViewSource.GetDefaultView(newValue);

base.OnItemsSourceChanged(oldValue, DataList);

if (this.IsFilter == true)

{

    foreach (DataGridColumn DGC in this.Columns)

    {

        FrameworkElementFactory Factory = new FrameworkElementFactory(typeof(StackPanel));

        FrameworkElementFactory LFactory = new FrameworkElementFactory(typeof(Label));

        LFactory.SetValue(Label.ContentProperty, DGC.Header.ToString());

        Factory.AppendChild(LFactory);

        if (DGC.GetType().Name == "DataGridTextColumn")

        {

            FrameworkElementFactory TFactory = new FrameworkElementFactory(typeof(TextBox));

            TFactory.SetValue(TextBox.MarginProperty, new Thickness(0));

            TFactory.SetValue(TextBox.WidthProperty, 150.00);

            TFactory.SetValue(TextBox.NameProperty, "txt" + DGC.Header.ToString());

            TFactory.AddHandler(TextBox.TextChangedEvent, new TextChangedEventHandler(TextBox_TextChanged), false);

            Factory.AppendChild(TFactory);

        }

        if (DGC.GetType().Name == "DataGridCheckBoxColumn")

        {

            FrameworkElementFactory TFactory = new FrameworkElementFactory(typeof(CheckBox));

            TFactory.SetValue(CheckBox.NameProperty, "txt" + DGC.Header.ToString());

            TFactory.AddHandler(CheckBox.ClickEvent, new RoutedEventHandler(CheckBox_Checked), false);

            Factory.AppendChild(TFactory);

        }

        DataTemplate Template = new DataTemplate();

        Template.DataType = typeof(HeaderedContentControl);

        Template.VisualTree = Factory;

        DGC.HeaderTemplate = Template;

    }

}

9. In the Textchanged event of TextBox controls and Click event of the Check box control set the filter property of DataList to the private function "CustomFilter" and write the following code to filter the DataGrid. Above I have explained about the custom filter function.
 
Code of Text Change Event of TextBox

TextBox STB = (TextBox)sender;

this.SearchValue = STB.Text;

ContentPresenter CP =(ContentPresenter) STB.TemplatedParent;        

DataGridColumnHeader DGCH = (DataGridColumnHeader)CP.TemplatedParent;

DataGridColumn DGC = DGCH.Column;

this.ColumnName = DGC.Header.ToString();

this.Datalist.Filter = this.CustomeFilter;
          
Code of Click Event of Check Box

           

CheckBox CB = (CheckBox)sender;

this.SearchValue = CB.IsChecked;

ContentPresenter CP = (ContentPresenter)CB.TemplatedParent;

DataGridColumnHeader DGCH = (DataGridColumnHeader)CP.TemplatedParent;

DataGridColumn DGC = DGCH.Column;

this.ColumnName = DGC.Header.ToString();

this.Datalist.Filter = this.CustomeFilter;