WPF Custom DataGrid in C#

Kailash Chandra Behera | Friday, June 26, 2020

Introduction

WPF Custom DataGrid in C# provide code snippet to build a WPF custom DataGrid that has feature to search and filter the data. here we will demonstrate to create the custom WPF DataGrid programmatically using C#.

WPF Custom DataGrid in C#

This demonstration creates a Custome DataGrid control by inheriting the base control class System.Windoes.Controls.DataGrid and overrides some methods to implement data searches and data filters based on the user inputs.

The Custom Data Grid searches data from each cell and applies the background and foreground color to the cell that satisfies the search criteria. It has some public properties that assist in finding the value of cells; Those are given below.

wpf grid programmatically

WPF DataGrid Search Filter (WPF Custom DataGrid in C#)

This custom data grid class contains one public property named IsFilter that enables DataGrid to Filterable, if IsFilter property is true, it shows text boxes( if datatype is string or int )and checkbox (if datatype is boolean) in each column header. Apart from this property, it contains some other property as well, and that are mentioned in the below.

WPF DataGrid Search (WPF Custom DataGrid in C#)

List of public properties of customs DataGrid used for make DataGrid searchable.

  1. IsEnableSearch(bool) : Makes enables the custom DataGrid to search data.
  2. SearchFieldName(string) : The name of the field to whose value is to be searched
  3. MatchDataBGColor(Brush) : sets the background color of the cell that contains the search data.
  4. MatchDataFGColor(Brush) : sets the foreground color of the cell that contains the search data.

Functions of customs DataGrid used to make DataGrid searchable.

FindVisualChildren is an add-on function which helps to find out the child controls(The TextBoxes resides in DataGrid cell) whose value is to be searched in the Datagrid using the System.Windows.Media.VisualTreeHelper class.

 public static IEnumerable<T> FindVisualChildren<T>(DependencyObject ParentControl) where T : DependencyObject  
 {  
   if (ParentControl != null)  
   {  
     for (int i = 0; i < VisualTreeHelper.GetChildrenCount(ParentControl); i++)  
     {  
       DependencyObject ChildControl = VisualTreeHelper.GetChild(ParentControl, i);  
       if (ChildControl != null && ChildControl is T)  
       {  
         yield return (T)ChildControl;  
       }  
       foreach (T ChildOfChildControl in FindVisualChildren<T>(ChildControl))  
       {  
         yield return ChildOfChildControl;  
       }  
     }  
   }  
  }  

FindVisualChildren() for WPF Custom DataGrid in C#

SearchTextBox_TextChanged is an event fired by the TextChange of TextBoxes used to search data in DataGrid.The TextChange event finds the search value from each cell of the DataGrid. If the condition is satisfied then it sets the foreground and background colors of your DataGrid cell.

 private void SearchTextBox_TextChanged(object sender, RoutedEventArgs e)  
 {  
   TextBox TB = (TextBox)sender;  
  foreach(DataGridColumn DGC in this.Columns)  
  {  
    for (int ind = 0; ind < this.Items.Count; ind++)  
    {  
      FrameworkElement FE = DGC.GetCellContent(this.Items[ind]);  
      if (FE!=null && FE.GetType().Name == "TextBlock")  
      {  
        TextBlock TX = (TextBlock)FE;  
        if (TX != null)  
        {  
          if (!string.IsNullOrEmpty(TB.Text) && TX.Text.Contains(TB.Text))  
          {  
            System.Windows.Media.BrushConverter BC = new System.Windows.Media.BrushConverter();  
            TX.Background = this.MatchDataBGColor;  
            TX.Foreground = this.MatchDataFGColor;  
          }  
          else  
          {  
            TX.Background = System.Windows.Media.Brushes.White;  
            TX.Foreground = System.Windows.Media.Brushes.Black;  
          }  
        }  
      }  
    }  
   }  

SearchTextBox_TextChanged() for WPF Custom DataGrid in C#

OnItemsSourceChanged calls the function mentioned above (FindVisualChildren) that will use the reference of the text box controls whose text is to be searched in the data grid and add the Text change event handler to your TextBox.

 protected override void OnItemsSourceChanged(System.Collections.IEnumerable oldValue, System.Collections.IEnumerable newValue)  
 {  
   //code searchs the textbox control that exists in the parent of datagrid  
   base.OnItemsSourceChanged(oldValue, newValue);  
   if (this.IsEnableSearch == true &&!string.IsNullOrEmpty(this.SearchTextBoxName))  
   {  
     foreach (TextBox tb in FindVisualChildren<TextBox>(this.Parent))  
     {  
       if (this.SearchTextBoxName == tb.Name)  
         {  
           this.SearchTextBox = tb;  
           this.SearchTextBox.TextChanged += new TextChangedEventHandler(SearchTextBox_TextChanged);  
         }  
      }  
    }  
 }  

OnItemsSourceChanged() for WPF Custom DataGrid in C#

Demonstration: WPF DataGrid Search (WPF Custom DataGrid in C#)

  1. Start Visual Studio, in the start page create a new project. Select the class library temple then rename it to Searchable Data Grid.

  2. Rename the class1 to SearchableDataGrid then inherit it from System.Windows.Controls.DataGrid. Add above public and private property SearchTextBox.

     publicstring SearchTextBoxName {get; set; }  
     public bool IsEnableSearch { get;set; }  
     public System.Windows.Media.Brush MatchDataBGColor{ get;set; }  
     public System.Windows.Media.Brush MatchDataFGColor{ get;set; }  
     private TextBox SearchTextBox {get; set; }  
    
  3. In the default constructor of the class, initializae and set the default value of the public properties.

     public SearchableDataGrid()  
     {  
       this.IsEnableSearch =false;  
       this.MatchDataBGColor= System.Windows.Media.Brushes.Yellow;  
       this.MatchDataFGColor= System.Windows.Media.Brushes.Gray;  
     }  
    
  4. Copy the FindVisualChildren function and paste it in the SearchableDataGrid class below the constructor.

  5. Copy the OnItemsSourceChanged function and paste it in the SearchableDataGrid class below the FindVisualChildren function.

  6. Copy the SearchTextBox_TextChanged function and paste it in the SearchableDataGrid class below the OnItemsSourceChanged function.

  7. Add the related references(namespaces) to the class.

  8. Now your class is ready and you are done with the WPF Custom Grid in C# for searchable, you can use it in XAML file like the default DataGrid you are using.

WPF DataGrid Filter (WPF Custom DataGrid in C#)

List of public properties of customs DataGrid used for make DataGrid searchable and will be used out side the Custom DataGrid class.

  1. IsFilter (bool) : Boolean data type, enable s DataGrid to Filterable.
  2. ColumnName (string) : It is also private property is column name of Custome Data Grid whose cell value will be searched.
  3. SearchValue (Object) : It is the private property whose value will be searched in the Data Grid.
  4. 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.

Functions of customs DataGrid used to make DataGrid filterable.

OnInitialized This function is overridden from base class(Base DataGrid) used toinitialize the properties.

 protected override void OnInitialized(EventArgs e)   
  {   
      base.OnInitialized(e);  
      this.DataList = null;  
      this.SearchValue = null;  
      this.ColumnName = "";  
      this.IsFilter = false;  
  }   

OnItemSourceChanged this function is main building block of WPF DataGrid Filter, The templates are added in to the heade of each columns of Custome DataGrid such as TextBox or CheckBox control in this function. 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.

 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;   
      }   
     }   
    }   

OnItemsSourceChanged() for WPF Custom DataGrid in C#

CheckBox_Checked is used to filter data from custom grid when checkbox column is there in DataGrid. It executes when the CheckBox(Used to filet) event fiers.

  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;   
    }   

CheckBox_Checked() for WPF Custom DataGrid in C#

TextBox_TextChanged this is used for WPF filter DataGrid with textbox, It executes when textchange event is fires from the TextBox(used to filter data).

 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;   
    }   

TextBox_TextChanged() for WPF Custom DataGrid in C#

CustomeFilter is called inside the TextBox_TextChanged function to match grid data against the value passed for filter.

 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());   
    }   

CustomeFilter() for WPF Custom DataGrid in C#

Demonstration: WPF DataGrid Filter (WPF Custom DataGrid in C#)

  1. Add a class into project and rename the class1 to FilterableDataGrid then inherit it from System.Windows.Controls.DataGrid.

  2. Add below public and private property to class.

     private ICollectionView Datalist { get; set; }  
         private object SearchValue { get; set; }  
         public string ColumnName { get; set; }  
         public bool IsFilter { get; set; }  
    
  3. In the default constructor of the class, initializae and set the default value of the IsFilter properties.

     public FilterableDataGrid()  
     {  
        this.IsFilter = false;
     }  
    
  4. Copy the OnInitialized function and paste it in the FilterableDataGrid class below the constructor.

  5. Copy the OnItemsSourceChanged function and paste it in the FilterableDataGrid class below the OnInitialized function.

  6. Copy the CheckBox_Checked function and paste it in the FilterableDataGrid class below the OnItemsSourceChanged function.

  7. Copy the SearchTextBox_TextChanged function and paste it in the FilterableDataGrid class below the CheckBox_Checked function.

  8. Copy the CustomeFilter function and paste it in the FilterableDataGrid class below the SearchTextBox_TextChanged function.

  9. Add the related references(namespaces) to the class.

  10. Now your class is ready and you are done with the WPF Custom DataGrid in C# for filtarable, you can use it in XAML file like the default DataGrid you are using.

Related Articles

  1. WPF Application using MVVM In C#
  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

Here we learned from demonstration how to create two WPF Custom DataGrid in C# with search and filter feature. also learned to make the wpf search in datagrid with textbox and to create wpf datagrid filter mvvm. I hope you have enjoyed it a lot.

Thanks