DataFilter for WinForms | ComponentOne
Data Filters / Custom Filter
In This Topic
    Custom Filter
    In This Topic

    The DataFilter control allows you to create custom filters which can replace the default filter editors at runtime. It provides CustomFilter class which needs to be inherited for defining a custom filter. Inheriting the CustomFilter class provides access to its properties and methods which can further be used to create a custom filter.

    Following example shows how you can create and add custom filter to the DataFilter control. It demonstrates how you can filter the car models using the MultiSelect control as a part of the DataFilter control UI.

    1. Define a custom filter by creating a new class which inherits the CustomFilter class. In the class constructor, use Control property of the CustomFilter class to specify the custom control that you want to use to perform filtering in the DataFilter control. For example, the following code is used for defining a custom filter, ModelFilter, to filter the data using the MultiSelect control as a filter within the DataFilter control.
      'Inherit the CustomFilter class to define a custom filter
      Public Class ModelFilter
          Inherits CustomFilter
      
         Private _multiSelect As C1MultiSelect
      
         'Customize settings of the MultiSelect control
          Public ReadOnly Property MultiSelect As C1MultiSelect
              Get
                  Return _multiSelect
              End Get
          End Property
      
              Public Sub New()
                      'Sets the control that represents the Custom filter to the
                      '"Control" property
                      Control = (_multiSelect, New C1MultiSelect() With {
                      .Height = 50,
                      .Placeholder = "Model of car",
                      .AutoCompleteMode = AutoCompleteMode.SuggestAppend
                              })
              _multiSelect.SelectionChanged += MultiSelect_SelectionChanged
      
      End Sub
      End Class
      
      //Inherit the CustomFilter class to define a custom filter
      public class ModelFilter : CustomFilter
      {
              private C1MultiSelect _multiSelect;
      
          //Customize settings of the MultiSelect control
          public C1MultiSelect MultiSelect { get { return _multiSelect; } }
      
          public ModelFilter()
          {
              //Sets the control that represents the Custom filter to the
              //"Control" property
              Control = _multiSelect = new C1MultiSelect() { Height = 50,
                  Placeholder = "Model of car", AutoCompleteMode =
                  AutoCompleteMode.SuggestAppend };
              _multiSelect.SelectionChanged += MultiSelect_SelectionChanged;
          }
      }
      
    2. Bind the MultiSelect control with data. In this example, we are binding the control with data using the SetTagList method.
      'Bind the MultiSelect control with data
      _multiSelect.BindingInfo.DataSource = tagSource
      _multiSelect.BindingInfo.DisplayMemberPath = PropertyName
      End Sub
      
      public void SetTagList(object tagSource)
      {
          //Bind the MultiSelect control with data
          _multiSelect.BindingInfo.DataSource = tagSource;
          _multiSelect.BindingInfo.DisplayMemberPath = PropertyName;
      }
      
    3. Raise the ValueChanged event of the CustomFilter class in the SelectionChanged event of the MultiSelect control which gets fired when the user selects values from the MultiSelect control. This notifies the DataFilter control about the change in filter values.
      Private Sub MultiSelect_SelectionChanged(ByVal sender As Object, ByVal e As EventArgs)
      'Raises the ValueChanged event of the custom filter
      'to apply filtering to grid
          OnValueChanged()
      End Sub
      
      private void MultiSelect_SelectionChanged(object sender, EventArgs e)
      {
          //Raises the ValueChanged event of the custom filter 
          //to apply filtering to grid.
          OnValueChanged();
      }
      
    4. Implement the GetExpression abstract method of the CustomFilter class to create and return the filter expression which is to be used to filter the values in the data aware control.
      Protected Overrides Function GetExpression() As Expression
                  'Creates and returns the filter expression
              Dim ce = New CombinationExpression() With {
                  .FilterCombination = FilterCombination.[Or]
              }
      
              For Each item In _multiSelect.SelectedItems
                  ce.Expressions.Add(New OperationExpression() With {
                      .FilterOperation = FilterOperation.Equal,
                      .Value = item.Value,
                      .PropertyName = PropertyName
                  })
              Next
      
              Return ce
          End Function
              'This property determines whether the filter is applied or not
          Public Overrides ReadOnly Property IsApplied As Boolean
              Get
                  Return MyBase.IsApplied AndAlso _multiSelect.SelectedItems.Count > 0
              End Get
          End Property
      
      protected override Expression GetExpression()
      {
          //Creates and returns the filter expression 
          var ce = new CombinationExpression() { FilterCombination =
              FilterCombination.Or };
          foreach (var item in _multiSelect.SelectedItems)
              ce.Expressions.Add(new OperationExpression() {
                  FilterOperation = FilterOperation.Equal,
                  Value = item.Value, PropertyName = PropertyName });
          return ce;
      }
      
      //This property determines whether the filter is applied or not
      public override bool IsApplied => base.IsApplied &&
          _multiSelect.SelectedItems.Count > 0;
      
    5. Add the created custom filter, ModelFilter, to the DataFilter control to filter the car models shown in the FlexGrid control.
      Dim _carsTable As DataTable
      
      Public Sub New()
          InitializeComponent()
          Me.Load += Form1_Load
      End Sub
      
      Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs)
          Dim con As OleDbConnection = New OleDbConnection(
                      "provider=microsoft.jet.oledb.4.0;Data Source=" & 
                      Environment.GetFolderPath(Environment.SpecialFolder.Personal) & 
                      "\ComponentOne Samples\Common\C1NWind.mdb")
          _carsTable = New DataTable()
          New OleDbDataAdapter("Select * from Cars", con).Fill(_carsTable)
          c1DataFilter1.DataSource = GetCars().ToList()
          c1FlexGrid1.DataSource = GetCars().ToList()
              
              'Initializes the Custom Model filter. This filter
          'allows you to filter the car models using the
              'MultiSelect control
          Dim modelFilter = New ModelFilter() With {
              .HeaderText = "Model",
              .PropertyName = "Model"
          }
              'Sets the data for the MultiSelect control
          modelFilter.SetTagList(GetCars().ToList())
              
              'Customizes the MultiSelect control to display
              'not more than 5 items in the control's header
          modelFilter.MultiSelect.MaxHeaderItems = 5
              
              'Adds the custom filter to the FilterCollection
          c1DataFilter1.Filters.Add(modelFilter)
              
              'Subscribe to the FilterChanged event
          c1DataFilter1.FilterChanged += C1DataFilter1_FilterChanged
      End Sub
      
      Private Sub C1DataFilter1_FilterChanged(ByVal sender As Object, ByVal e As EventArgs)
              'Updates the data aware control with filtered data
          c1FlexGrid1.DataSource = c1DataFilter1.View.Cast(Of Car)().ToList()
      End Sub
      
      Public Iterator Function GetCars() As IEnumerable(Of Car)
          Dim carsTable = _carsTable
      
          For Each row As DataRow In carsTable.Rows
              Yield New Car With {
                  .Brand = row.Field(Of String)("Brand"),
                  .Category = row.Field(Of String)("Category"),
                  .Description = row.Field(Of String)("Description"),
                  .Liter = row.Field(Of Double)("Liter"),
                  .Model = row.Field(Of String)("Model"),
                  .Picture = row.Field(Of Byte())("Picture"),
                  .Price = row.Field(Of Double)("Price"),
                  .TransmissAutomatic = row.Field(Of String)("TransmissAutomatic"),
                  .ID = row.Field(Of Integer)("ID")
              }
          Next
      End Function
      
      DataTable _carsTable;
      public Form1()
      {
          InitializeComponent();
          this.Load += Form1_Load;
      }
      
      private void Form1_Load(object sender, EventArgs e)
      {
          OleDbConnection con = new OleDbConnection(
              "provider=microsoft.jet.oledb.4.0;Data Source=" +
              Environment.GetFolderPath(Environment.SpecialFolder.Personal) +
              "\\ComponentOne Samples\\Common\\C1NWind.mdb");
          _carsTable = new DataTable();
      
          new OleDbDataAdapter("Select * from Cars", con).Fill(_carsTable);
      
          c1DataFilter1.DataSource = GetCars().ToList();
          c1FlexGrid1.DataSource = GetCars().ToList();
      
          //Initializes the Custom Model filter. This filter
          //allows you to filter the car models using the
          //MultiSelect control
          var modelFilter = new ModelFilter()
          {
              HeaderText = "Model",
              PropertyName = "Model",                
          };
      
          //Sets the data for the MultiSelect control
          modelFilter.SetTagList(GetCars().ToList());
      
          //Customizes the MultiSelect control to display 
          //not more than 5 items in the control's header
          modelFilter.MultiSelect.MaxHeaderItems = 5;
      
          //Adds the custom filter to the FilterCollection
          c1DataFilter1.Filters.Add(modelFilter);
      
          //Subscribe to the FilterChanged event
          c1DataFilter1.FilterChanged += C1DataFilter1_FilterChanged;
      }
      
      private void C1DataFilter1_FilterChanged(object sender, EventArgs e)
      {
          //Updates the data aware control with filtered data
          c1FlexGrid1.DataSource = c1DataFilter1.View.Cast<Car>().ToList();
      }
      
      public IEnumerable<Car> GetCars()
      {
          var carsTable = _carsTable;
          foreach (DataRow row in carsTable.Rows)
          {
              yield return new Car
              {
                  Brand = row.Field<string>("Brand"),
                  Category = row.Field<string>("Category"),
                  Description = row.Field<string>("Description"),
                  Liter = row.Field<double>("Liter"),
                  Model = row.Field<string>("Model"),
                  Picture = row.Field<byte[]>("Picture"),
                  Price = row.Field<double>("Price"),
                  TransmissAutomatic = row.Field<string>("TransmissAutomatic"),
                  ID = row.Field<int>("ID")
              };
          }
      }
      

    Similarly, you can create any other custom filters.