WPF Datagrid Filterable Column

This blog provides a code example for creating a custom DataGrid in WPF with built-in data filtering functionality.

WPF Datagrid Filterable Column

Getting Started

The DataGrid in WPF is powerful and versatile, commonly used for displaying and manipulating tabular data. However, out of the box, it doesn't support column filtering like Excel does. This post shares C# code to create a DataGrid in WPF with filterable columns, allowing users to filter data dynamically.

This code snippet creates a custom DataGrid control in C# by inheriting from the base control System.Windows.Controls.DataGrid. It filters the data based on user input. This custom DataGrid class contains a public property named IsFilter, which enables filtering. If the IsFilter property is set to true, it displays text boxes (for string or int data types) and checkboxes (for bool data types) in each column header. In addition to this property, the class includes several other properties, which are described below.

  1. DataList:This properties is the object of ICollectionView. The ICollectionView interface belongs to System.ComponentModel. Its monst powerfull feature is, it enables collections to have the functionality of current record management,Custome sorting, filtering and grouping. The DataList Property contais items list binded with DataGrid and pases as items source of base DataGrid.
  2. SearchValue::- It is the private property whose value will be searched in the Data Grid. Data type is Object.
  3. ColumnName:It is also private property is column name of Custome Data Grid whose cell value will be searched. Data Type is string.
  4. IsFilter:Boolean data type, enable s DataGrid to Filterable.

Above mentioned properties are used for out side of Custom DataGrid class, apart from that this class overrides two base class(Base DataGrid) functions, that is discussed in the below.

  1. OnInitialized: This function is used for initialize the properties.
  2. OnItemSourceChanged:

    In this function, templates are added in to the heade of each columns of Custome DataGrid such as TextBox or CheckBox control. If the data type of column is DagaGridTextColumn than TextBox will be added into the header or the data type f column is DataGridCheckBoxColumn than CheckBox will be added in the header.

Code Shippet

Below code example contains all the code to create Custom DataGrid control in WPF.

 using System;  
 using System.Collections.Generic;  
 using System.Linq;  
 using System.Text;  
 using System.Windows.Controls;  
 using System.Windows;  
 using System.Windows.Media;  
 using System.Windows.Controls.Primitives;  
 using System.IO;  
 using System.ComponentModel;  
 using System.Windows.Data;  
 using System.Reflection;  
 namespace FilterableGridInWpf  
 {  
   public class FilterableDataGrid : DataGrid  
   {  
     private ICollectionView Datalist { get; set; }  
     private object SearchValue { get; set; }  
     public string ColumnName { get; set; }  
     public bool IsFilter { get; set; }  
     public FilterableDataGrid()  
     {  
       this.IsFilter = false;  
     }  
     protected override void OnInitialized(EventArgs e)  
     {  
       base.OnInitialized(e);  
     }  
     protected override void OnItemsSourceChanged(System.Collections.IEnumerable oldValue, System.Collections.IEnumerable newValue)  
     {  
       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;  
         }  
       }  
     }  
     void CheckBox_Checked(object sender, RoutedEventArgs e)  
     {  
       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;  
     }  
     private void TextBox_TextChanged(object sender, RoutedEventArgs e)  
     {  
       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;  
     }  
     private bool CustomeFilter(object item)  
     {  
       Type TP = item.GetType();  
       PropertyInfo PI = TP.GetProperty(this.ColumnName);  
       object[] obj=new object[ this.SearchValue.ToString().Length];  
       string values = PI.GetValue(item,obj).ToString();  
       values = values.ToUpper();  
       return values.StartsWith(this.SearchValue.ToString().ToUpper());  
     }  
   }  
 }  

WPF Datagrid
WPF Datagrid  Filterable Column

Related Articles

  1. Data Validation in WPF
  2. WPF Round Corner Button with click effects
  3. Round Corner PasswordBox in WPF
  4. Round Corner TextBox in WPF
  5. WPF Custom Datagrid Control(Filterable)
  6. WPF Round Corner ListBox
  7. Custom RadioButtonListBox With Image
  8. RadiobuttonList in WPF
  9. Custom CheckedListBox in WPF

Summary

By using CollectionViewSource and binding it to your UI, you can easily implement filterable columns in a WPF DataGrid. This improves usability, especially in data-heavy applications, and mimics filtering functionality familiar to users of tools like Excel.

Thanks

Kailash Chandra Behera

I am an IT professional with over 13 years of experience in the full software development life cycle for Windows, services, and web-based applications using Microsoft .NET technologies.

Previous Post Next Post

نموذج الاتصال