Sep 6, 2011

FilterableDataGridView (C#.NET): A DataGridView control with built-in Filtering

During developing my project I was left without Internet access for a week, and I couldn't search for an easy and already written solution for my problem, so I decided to create my own solution.

I had a DataGridView on one of my forms with a DataSource linked to an SQL server through LINQ to SQL and I wanted to be able to filter the result rows, based on user input. Since the clients (the users of my program) will connect to the database through the Internet, some of them via poor connections, I didn't want to make a new query with each change of the filter. I found out that the DataGridViewRow has a Visible property, and it looked like an efficient way to set this according to the filters. So I created a new class inheriting from the DataGridView, and added some extra functionality to support filtering.



My solution consists of two classes:

  1. FilterItem
  2. FilterableDataGridView

1. FilterItem

This class represents a filter which can be applied to a FilterableDataGridView. It's basically two strings, one for storing the filter text, and the other to select the columns for the filter check. (This was a necessary requirement to be able to select the columns, since I didn't want it to search in my hidden ID column for example).
But the interesting part of this class is an event which gets fired every time the filter changes, and makes it possible that changing the filter text will apply the filter again without any additional method calls. See usage below.

The code:

2. FilterableDataGridView


The class inherits from DataGridView. Contains a collection of FilterItems as a public property named Filters, you can add your filters to this list. The collections type is ObservableCollection<>, which is only available from .NET 4.0, so this sets the minimum requirements of the whole project.
When the property’s value is set, the object subscribes to the collection’s CollectionChanged event, it’s handled the following way:
  • If a new FilterItem is added, it subscribes to its FilterChanged event.
  • If an item is removed, it unsubscribes from its event.
  • Finally the Filter() method is called.
The Filter method checks every row for every filter and decides (sets) if the row should be visible or not.

The Code:





Usage:

The FilterItem properties:

  • Filter: Set a string that has to be found in the rows values. Upper or down case doesn't matter. The ‘|’ character will translate as OR, thus any of the strings on the sides of ‘|’ can satisfy the filtering condition. For an AND expression please use multiple FilterItems, since a row has to meet the expressions of all of FilterItems present in the FilterableDataGridView Filters collection. Regular expressions are not supported, yet. 
  • FilterColumn: List the columns where the search should be done, use '|' to separate column names.

e.g.:

Using the FilterableDataGridView:

Let's say you have a TextBox (named textbox1) and you want the FilterableDataGridView to filter when the text changes in the textbox.
  1. Add a FilterableDataGridView to your Form, from the toolbox.
    Make sure to implement the proper using directive:
    using Rankep.FilterableDataGridView;
    
  2. Create a FilterItem which you will use to update the filter. (Don't create a new one every time, or if you do remember to delete the old ones from the list, because all of the Filters added to the FilterableDataGridView.Filters list will be checked and will have to be satisfied.)
    Example:

    public partial class Form1 : Form
        {
            //A FilterItem for the text in the TextBox
            private FilterItem textboxFilter;
            ...
        }
    
  3. Assign a new FilterItem to it.
    Example:
    textboxFilter = new FilterItem("", "Name|Address|Tel");
    
  4. Subscribe to the textbox1 TextChanged event, and change the textboxFilter.Filter to the Text property of the Textbox. (Check if the FilterableDataGridView.Filters contains the FilterItem, if not add it).
    Example:
    private void textBox1_TextChanged(object sender, EventArgs e)
            {
                //Change the filter Text
                textboxFilter.Filter = textBox1.Text;
    
                //If the FilterableDataGridView doesn't contain the filter yet
                if (!filterableDataGridView1.Filters.Contains(textboxFilter))
                    //then add it
                    filterableDataGridView1.Filters.Add(textboxFilter);
            }
    

Using the precompiled .dll component:

  1. Copy the FilterableDataGridView.dll file to your project directory.
  2. Open your project in Visual Studio
  3. Right click on the Toolbox in the category where you would like to add the component.
  4. Select Choose Items…
  5. Browse…
  6. Open the FilterableDataGridView.dll
  7. Make sure that the checkbox in front of FilterableDataGridView is checked, and click OK.
  8. The component has now appeared in the toolbox, and you can use it as any other components. Detailed usage is described above.
Downloads:
FilterableDataGridView precompiled (.dll)
FilterableDataGridView source code
Source code + sample

Feel free to use it, copy it, share it, improve it, ...

Any questions, advises are welcome in the comments.

2 comments:

  1. I have tried this but my datagridview is not been filtered when i run the program...where could the problem be?

    Thanks

    ReplyDelete