{"id":20360708,"url":"https://github.com/farosch/dgvfilterpopup","last_synced_at":"2025-05-08T06:32:42.212Z","repository":{"id":29809687,"uuid":"122829864","full_name":"farosch/DgvFilterPopup","owner":"farosch","description":"A flexible library to add filtering capabilities to a DataGridView","archived":false,"fork":false,"pushed_at":"2021-12-07T23:00:14.000Z","size":401,"stargazers_count":11,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-11-08T10:30:44.292Z","etag":null,"topics":["datagridview","filter-controls","filtering","winform"],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/farosch.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-02-25T11:27:22.000Z","updated_at":"2024-04-10T18:26:45.000Z","dependencies_parsed_at":"2022-09-19T13:50:58.781Z","dependency_job_id":null,"html_url":"https://github.com/farosch/DgvFilterPopup","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/farosch%2FDgvFilterPopup","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/farosch%2FDgvFilterPopup/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/farosch%2FDgvFilterPopup/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/farosch%2FDgvFilterPopup/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/farosch","download_url":"https://codeload.github.com/farosch/DgvFilterPopup/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224708962,"owners_count":17356521,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["datagridview","filter-controls","filtering","winform"],"created_at":"2024-11-14T23:42:42.109Z","updated_at":"2024-11-14T23:42:44.058Z","avatar_url":"https://github.com/farosch.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# DgvFilterPopup\nBased on the original work of [Vincenzo Rossi](https://www.codeproject.com/script/Membership/View.aspx?mid=3713668)'s [DgvFilterPopup](https://www.codeproject.com/Articles/33786/DataGridView-Filter-Popup).\n\n![picture alt](Images/Overview.png)\n\n## Builds\n| Branch | Status |\n| --- | --- |\n| main | [![Build](https://github.com/farosch/DgvFilterPopup/actions/workflows/build_and_test.yml/badge.svg?branch=main)](https://github.com/farosch/DgvFilterPopup/actions/workflows/build_and_test.yml) |\n| develop | [![Build](https://github.com/farosch/DgvFilterPopup/actions/workflows/build_and_test.yml/badge.svg?branch=develop)](https://github.com/farosch/DgvFilterPopup/actions/workflows/build_and_test.yml) |\n\n## Installation\nSimply install the [nuget package](https://www.nuget.org/packages/DgvFilterPopup/): ![NuGet](https://img.shields.io/nuget/v/DgvFilterPopup?style=flat-square)\n\n    PM\u003e Install-Package DgvFilterPopup -Version 1.3.0\n\n## Introduction\nI was looking for an easy and flexible grid filtering mechanism to use with new and old applications. I've found no preexisting solutions that fully satisfy my needs. So, I decided to make my own filtering library. The goals I've tried to reach are:\n\n* Easy to integrate: Availability of a \"few lines of code\" usage to satisfy the needs of rapid integration.\n* User Friendly: Nice to look, easy to use.\n* Not code pervasive: Using a DataGridView derivation would constrain people to re-declare their instances. Moreover, this could be in conflict with existing grid derivations.\n* Flexible: There are never enough filters in the world!\n\n## Using the Code\nThis is for eager people. The promised \"few lines of code\" are just one. Add the DgvFilterPopup.dll to your references. Write somewhere a line like this:\n\n    DgvFilterManager filterManager = new DgvFilterManager(dataGridView1);\n\nThat's all. Your grid is now able to filter the column values. Right-click on the column headers to see a popup with different filtering features, based on the clicked column data type.\n\n**Note:** Your grid must be data-bound to a `DataView`, `DataTable`, or a `BindingSource` resolving to one of these two.\n\n## Class Architecture\nThe three main classes are exposed in the following diagram:\n\n![picture alt](Images/BasicDiagram.png)\n\n### The DgvFilterManager Class\nThe `DgvFilterManager` class doesn't provide a user interface. Its work is to coordinate the interaction between the `DataGridView` and the visual filtering elements. When you assign a `DataGridView` to a `DgvFilterManager`, the latter attaches some handlers to respond to right click on column headers and to perform some custom painting on the grid. When the user right clicks a column header, the `DgvFilterManager` shows a popup near the column. This popup is a control that serves as a host for other controls, one for each column. Only one of these child controls is visible at a time, based on the clicked column. We have one filter host control and many column filter child controls.\n\nThe *filter host* control must be a derivation of the `DgvBaseFilterHost` class, while filter controls must be derived from the `DgvBaseColumnFilter` class. These two classes don't provide any user interface themselves.\n\nAs a default, the `DgvFilterManager` uses a standard host implementation, named `DgvFilterHost`, and depending on each column type and data type, one of the filter standard implementations (see below): `DgvTextBoxColumnFilter`, `DgvCheckBoxColumnFilter`, `DgvComboBoxColumnFilter` or `DgvDateColumnFilter`.\n\nWhen a `DataGridView` is attached to the manager, the latter performs the following actions:\n\n* It creates a *filter host* that is an instance of the DgvFilterHost class. If you have already provided a filter host, this step is skipped.\n* It creates a list of `DgvBaseColumnFilters`, one per column, and initializes each element to a specialization of `DgvBaseColumnFilter`. If `AutoCreateFilters` is false, this step is skipped.\nYou can force a specific *column filter* type for a certain column, intervening in this process through the `ColumnFilterAdding` event. You can also intervene, after the auto-creation process, accessing the filter instances through one of the two indexers provided by the manager, and replacing them with user-chosen instances.\n\n### The DgvBaseFilterHost Class\nThe purpose of the *filter host* control is to show a popup near a right-clicked column and to host child *column filter* controls. When the popup is shown, only the *column filter* control related to the right-clicked column is visible. `DgvBaseFilterHost` is a derivation of `UserControl`, and provides functionalities to cooperate with `DgvFilterManager`.\n\n**Note:** This class is intended as an `abstract` class. However, declaring it as abstract would generate errors within the designer when designing derived classes.\n\nIn your derivation, you have to provide a host area (such as a panel) and override the `FilterClientArea` to return it. Also, create visual elements for *remove filter, remove all filters, apply filter*, and use the `DgvFilterManager` methods `ActivateFilter` and `ActivateAllFilters` to make them alive.\n\n### The DgvBaseColumnFilter Class\nThe purpose of a *column filter* control is to contain visual elements, allowing the end user to construct a filter. When inheriting from it, you can work just like creating any other user control. This class is a derivation of `UserControl`, and provides functionalities to cooperate with `DgvFilterManager`.\n\n**Note:** This class is intended as an `abstract` class. However, declaring it as abstract would generate errors within the designer when designing derived classes.\n\nYou should override `OnFilterExpressionBuilding` to provide a filter expression construction logic and to set the values of the `FilterExpression` and `FilterCaption` properties.\n\n## Standard Implementations\n![picture alt](Images/Hierarchy.png)\n\n### The DgvFilterHost Class\n![picture alt](Images/FilterHost.png)\n\nThis is the standard implementation of `DgvBaseFilterHost`. This class does nothing special. Most of the logic is in its base class. It just contains visual elements such as buttons and graphics, and a panel acting as the client area for child *column filter* controls.\n\n### The DgvTextBoxColumnFilter Class\n![picture alt](Images/TextBox.png)\n\nThis is one of the `DgvBaseColumnFilter` standard implementations. It's composed of a combobox containing a list of operators and a textbox in which to type the value of the filter. This *column filter* is used by default with DataGridViewTextBoxColumns, except when the bound data type is `DateTime`. The list of available operators is different between string types and numeric types.\n\n### The DgvTextBoxColumnFilter Class\n![picture alt](Images/CheckBox.png)\n\nA standard implementation for the filtering of checkbox columns. The only available operators are the equal and the general *null* and *not null* operators.\n\n### The DgvDateColumnFilter Class\n![picture alt](Images/Date.png)\n\nA standard implementation for the filtering of date columns.\n\n### The DgvComboBoxColumnFilter Class\n![picture alt](Images/ComboBox.png)\n\nA standard implementation for the filtering of combobox columns. By default, on textbox columns, the filter manager uses `DgvTextBoxColumnFilter` instances. However, you can force an instance of `DgvComboBoxColumnFilter` on such columns. In this case, the `DgvComboBoxColumnFilter` instance automatically creates a distinct list of values from the column data. You should do an explicit call to the `RefreshValues()` method when the underlying data changes.\n\n## Customizing\nIf *\"one line usage\"* is not sufficient for your needs, you can control the process of adding and showing filters in different ways.\n\n### Using a DgvComboBoxColumnFilter for Non-Combobox Columns\nUse one of the manager indexers to access the filter, and assign it an instance of the `DgvComboBoxColumnFilter` class.\n\n    DgvFilterManager fm = new DgvFilterManager(dataGridView1);\n    fm[\"CustomerID\"] = new DgvComboBoxColumnFilter();\n\n### Using Events\n#### ColumnFilterAdding\nUsing this manager event, you may force your preferred filter before the manager creates the predefined filter. The event is raised for each column in the grid when you set the `DataGridView` property.\n\n    ...\n    DgvFilterManager fm = new DgvFilterManager();\n    fm.ColumnFilterAdding += new ColumnFilterEventHandler(fm_ColumnFilterAdding);\n    fm.DataGridView = dataGridView1; // this raises ColumnFilterAdding events\n    ...\n    \n    void fm_ColumnFilterAdding(object sender, ColumnFilterEventArgs e) {\n      if (e.Column.Name == \"CustomerID\") {\n        e.ColumnFilter = new DgvComboBoxColumnFilter();\n      }\n    }\n\n#### PopupShowing\nThis manager event allows you to customize the filter host position when popped up.\n\n    ...\n    DgvFilterManager fm = new DgvFilterManager();\n    fm.DataGridView = dataGridView1;\n    // Customize the popup positioning.\n    fm.PopupShowing += new ColumnFilterEventHandler(fm_PopupShowing);\n    ...\n    \n    void fm_PopupShowing(object sender, ColumnFilterEventArgs e) {\n      DgvFilterManager fm = ((DgvFilterManager)sender);\n      Rectangle HeaderRectangle = \n        fm.DataGridView.GetCellDisplayRectangle(e.Column.Index,-1,true);\n      //Show the popup under the column header\n      fm.FilterHost.Popup.Show(fm.DataGridView, HeaderRectangle.Left, HeaderRectangle.Bottom);\n      e.Handled = true;\n    }\n\n#### FilterExpressionBuilding\n![picture alt](Images/Customizing.png)\n\nUsing the `DgvBaseColumnFilter` event, you can customize the filter expression building process. In the following code example, we add new operators and then manage them in the event handler. The `FilterExpression` and `FilterCaption` properties will be used by the manager to build the whole filter and to set the column caption.\n\n    ...\n    DgvDateColumnFilter OrderDate;\n    ...\n    DgvFilterManager fm = new DgvFilterManager(dataGridView1);\n    fm.DataGridView = dataGridView1; //after this line, column filters are created\n    \n    // Get the created column filter for OrderDate column\n    OrderDate = ((DgvDateColumnFilter)fm[\"OrderDate\"]);\n    \n    //Add some new operators\n    OrderDate.ComboBoxOperator.Items.Insert(0, \"This year\");\n    OrderDate.ComboBoxOperator.Items.Insert(1, \"1 year ago\");\n    OrderDate.ComboBoxOperator.Items.Insert(2, \"2 years ago\");\n    \n    //Add an handler\n    OrderDate.FilterExpressionBuilding += \n    new CancelEventHandler(OrderDate_FilterExpressionBuilding);\n    ...\n  \n    void OrderDate_FilterExpressionBuilding(object sender, CancelEventArgs e) {\n      int index = OrderDate.ComboBoxOperator.SelectedIndex;\n      if (index \u003c 3) { // the first 3 are the new operators\n        int year = (DateTime.Today.Year - index);\n        OrderDate.FilterExpression = \"(OrderDate\u003e='\" + year.ToString() + \"-1-1' \" \n                               + \"AND OrderDate\u003c='\" + year.ToString() + \"-12-31') \";\n        OrderDate.FilterCaption = OrderDate.OriginalDataGridViewColumnHeaderText \n                            + \"\\n = year \" + year.ToString();\n        e.Cancel = true;\n      }\n    }\n\n### Subclassing\nA more powerful way to customize your filters is through subclassing. You should think of the proposed standard implementations of `DgvBaseFilterHost` and `DgvBaseColumnFilter` as just some possible implementations.\n\n#### Creating Your Own Host\n![picture alt](Images/CustomHost.png)\n\nAs said above, derive from `DgvBaseFilterHost` and provide some visual elements. Add a container within your control to host the child filter controls, and return it by an override of the `FilterClientArea` property. The base class provides the necessary logic to cooperate with the manager, and provides some facilities helping to position the child filter controls and to adjust the host size. Another facility simplifies the creation of transparent skinned hosts, thanks to the method `BitmapToRegion` I've found in a very nice article by John O'Byrne.\n\n**Note:** A skinned host must be constrained to a fixed size. Be sure to inhibit the resize logic by overriding the `DoAutoFit` method. Also, keep in mind this limitation when designing your own host and your filters.\n\n    DgvFilterManager fm = new DgvFilterManager();\n    fm.FilterHost = new CustomizedFilterHost();\n    fm.DataGridView = dataGridView1;\n\n#### Creating Your Own Column Filters\n![picture alt](Images/CustomFilter.png)\n\nCreating new column filters is simple. Derive from `DgvBaseColumnFilter` and add your visual elements. Override `OnFilterExpressionBuilding` to provide filter building logic and, using `DataView.RowFilter` rules, assign a value to the `FilterExpression` property and a title to the `FilterCaption` property.\n\nRemember that the filter is applied when the user clicks on the *OK* button of the host. However, you can obtain an immediate filter application doing a call to the `RebuildFilter` method of the filter manager.\n\n## New Filters\nTo satisfy some requests, in the 1.1.0.0 update, I've introduced three new filter implementations:\n\n![picture alt](Images/ExtensionsDiagram.png)\n\n### The DgvMonthYearColumnFilter Class\n![picture alt](Images/DgvMonthYearColumnFilter.png)\n\nThis filter allows the user to select a month and a year. By setting the `YearMin` and `YearMax` properties, you can control the shown years range. Month names default to English, but you may provide culture-specific names by once setting the value of the static property `MonthCsvList` with a comma separated list of month names.\n\n### The DgvNumRangeColumnFilter Class\n![picture alt](Images/DgvNumRangeColumnFilter.png)\n\nUse this filter to allow the user to specify a range filter on numeric columns.\n\n### The DgvDateRangeColumnFilter Class\n![picture alt](Images/DgvDateRangeColumnFilter.png)\n\nUse this filter to allow the user to specify a range filter on date columns.\n\n## Conclusions\nIn this article, I've exposed the class architecture and common usage scenarios. This conceptual overview, I hope, will help you understand how it works. For detailed explanations and references, you can see the attached documentation.\n\n**Note:** To those interested in documenting their works, I've used these materials:\n\n* [XML Documentation Comments](http://msdn.microsoft.com/en-us/library/b2s063f7(VS.80).aspx) from MSDN\n* [Sandcastle v2.4.10520](http://www.microsoft.com/downloads/details.aspx?FamilyID=E82EA71D-DA89-42EE-A715-696E3A4873B2\u0026displaylang=en): A documentation command-line compiler from Microsoft\n* [Help File Builder 1.8.0.1 Beta](http://shfb.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=18639): A Sandcastle GUI (requires .NET 3.5) from Eric Woodruff\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffarosch%2Fdgvfilterpopup","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffarosch%2Fdgvfilterpopup","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffarosch%2Fdgvfilterpopup/lists"}