i00 BindingList with DataGridView
Simple to use BindingList and DataGridView that supports advanced LINQ filtering!
![]() | Please let me know if you use this in your projects by posting below. A simple "I am using this in my project" will suffice. |
Introduction
This project was designed to provide a simple way to add data to a list that could be filtered and sorted, with ease... but (as with most of my projects) this quickly grew to support lots of other features such as full LINQ filtering, a datagrid view that supports UIEditors, filtering plugins, a BindingNavigator that has filtering options and more!
Features
BindingListView
- Allows easy filtering
- Allows easy sorting
- Supports LINQ filtering
DataGridView
- UI Type Editor drawing on cells
- UI Type Editor support for cell editing
- Inbuilt column header menus for sorting and filtering options
- Data filtering plugins
- Highlighting of filtered text
- Faster than the standard DGV
- Images scale to fit cells
- Images can be selected by double clicking on an image cell
- Lists and allows Enum options to be selected with ease
BindingNavigatorWithFilter
- Adds filtering fields to the standard BindingNavigator
Implementation
To implement i00 BindingList into your project, first either:
- Add the
i00BindingList
project to your solution and reference it (recommended) - Reference the i00BindingList.exe file that is output from this project
- or you can bring all of *.vb files in the "i00BindingList" folder (from the zip) directly into your own project
Creating a Binding List
The Binding List can be created and filled just like any List(Of T)
:
'Create a i00BindingList.BindingListView of the required object... in this case "Person"
Dim blPersons As New i00BindingList.BindingListView(Of Person)
'... and to fill it:
Dim Person as New Person()
'fill person details here
blPersons.Add(Person)
Filtering a Binding List
The Binding List can be filtered by taking advantage of i00BindingList.BindingListView.Filter
property. The i00BindingList filters are in LINQ and support calls to functions from within your project itself. For example the following will filter our list to show all of the people born in 1982:
blPersons.Filter = "(Year([DOB]) = 1982)"
To access a Public Shared Function (in this case PeopleFunctions.IsInFootballTeam()
) in your project you can do so by going:
blPersons.Filter = GetType(PeopleFunctions).FullName & ".IsInFootballTeam([Me]) = True"
Note: that while using filtering [Me] and [Fields] must be in square brackets.
When filtering the Binding List the FilterChanged event is called.
Binding List Binding
The Binding List exposes a BindingSource
Property that can be used as a DataSource
for DataGridViews
, or as a BindingSource
for BindingNavigator
.
The DataGridView
The i00BindingList.DataGridView
inherits from DataGridView and can be used on custom data sources to allow support for UIEditors
. UIEditors
are part of the Net Framework and allow custom editors for items in the i00 DataGridView automatically as long as the AllowUIEditorCells
and DrawUIEditorCells
properties of the grid are set to true.
In the following you can see the ColorEditor
in action:
For more info on creating your own UIEditor
's check this article.
Filtering Plugins for the the DataGridView
If a i00BindingList.DataGridView
is bound to a i00BindingList.BindingListView
it will automatically allow filtering from the header based on each column's data type. These can be extended to provided advanced filtering via plugins (as pictured below)
Filter plugins are classes that implement i00BindingList.Plugins.iFilterPlugin
; they automatically get picked up and allow the addition of extra filters based on each fields data type. Projects require no reference to the plugins (if they are in external files), however you will need to place them in the applications path.
The download project includes three filters ColorFilter
(in the i00BindingList project), DateFilter
and RecentDateTimeFilter
(in the Test project).
Below is a list of implements and what they are used for after implementing iFilterPlugin
:
- Public ReadOnly Property
DataTypes
() As System.Type() - This should be set to return the data types (in an array) that we will be using this filter on. - Public ReadOnly Property
Dispaly
() As i00BindingList.Plugins.DisplayMethods - Sets when this filter will be displayed, options are DefaultHide, Always, DefaultShow - Public Sub
LoadFromFilter
(ByVal Filter As i00BindingList.AdvancedBindingSource.BasicFilterBase) - This is called when existing filter data (BasicFilterBase
) is loaded and should update the controls inMenuItems
accordingly. - Public Function
MenuItems
() As System.Collections.Generic.List(Of System.Windows.Forms.ToolStripItem) - Sets the list of controls that will be loaded into the menu for this filter. - Public Event
UpdateFilter
(ByVal sender As Object, ByVal e As i00BindingList.Plugins.UpdateFilterPluginEventArgs) - This should be raised when your controls cause the filter to be updated.
Below is an example of an iFilterPlugin
that is used to filter a date range:
Public Class DateFilter
Implements i00BindingList.Plugins.iFilterPlugin
#Region "Controls"
'This is a Series of controls that will be available through the DataGridView's filter menu
'This is the check box that when checked filters the dates as selected by the MonthCalendar,
'This exists as the MonthCalendar has no way to have NO date selected...
Private WithEvents tsiSelectDate As New i00BindingList.PersistentToolStripMenuItem() With {.Text = "Select a date or date range:"}
'This is the month calendar that allows the user to select a date period to filter by
Private WithEvents MonthCalendar As New MonthCalendar With {.MaxSelectionCount = Integer.MaxValue, .ShowTodayCircle = False}
'Returns the controls back to the plugin that we want to add to the filter menu
Public Function MenuItems() As System.Collections.Generic.List(Of System.Windows.Forms.ToolStripItem) Implements i00BindingList.Plugins.iFilterPlugin.MenuItems
MenuItems = New List(Of ToolStripItem)
Static ToolStripControlHost As New ToolStripControlHost(MonthCalendar)
MenuItems.Add(tsiSelectDate)
MenuItems.Add(ToolStripControlHost)
End Function
#End Region
#Region "Data Specifications"
'Returns an array of data types that we can use this filter on... in this case Date
Public ReadOnly Property DataTypes() As System.Type() Implements i00BindingList.Plugins.iFilterPlugin.DataTypes
Get
Return New System.Type() {GetType(Date)}
End Get
End Property
'Specifies when this plugin will be displayed
'this is also, somewhat, controlled by the use of the i00BindingList.Plugins.ActiveFilterPlugins on the object property itself
Public ReadOnly Property Dispaly() As i00BindingList.Plugins.DisplayMethods Implements i00BindingList.Plugins.iFilterPlugin.Dispaly
Get
Return i00BindingList.Plugins.DisplayMethods.DefaultShow
End Get
End Property
#End Region
#Region "Events"
'This is raised when our controls cause the filter to be updated...
'e.FilterBase is used to send back the BasicFilterBase that is created from the options selected from our controls
Public Event UpdateFilter(ByVal sender As Object, ByVal e As i00BindingList.Plugins.UpdateFilterPluginEventArgs) Implements i00BindingList.Plugins.iFilterPlugin.UpdateFilter
#End Region
#Region "BasicFilterBase"
'BasicFilterBase's basically allow the creation of "some-what automated" LINQ where statements, through the specification of certain parameters
'This is a BasicFilter that will be used to create a LINQ where clause from based on data we will get from our controls
Public Class BasicDateFilter
Inherits i00BindingList.AdvancedBindingSource.BasicFilterBase
'The data that we will be filtering on with our iFilterPlugin
Public DateFrom As Date
Public DateTo As Date
'Generates a basic LINQ where statement from the prams above
Public Overrides ReadOnly Property GetLinq() As String
Get
Return "CDate(Format(xItem.[" & Field & "], ""D"")) >= CDate(""" & DateFrom.ToString & """) AndAlso CDate(Format(xItem.[" & Field & "], ""D"")) <= CDate(""" & DateTo.ToString & """)"
End Get
End Property
End Class
#End Region
#Region "Filtering"
'This is called when the filter needs to be re-loaded
'for example if the date 1/1/1 -> 2/2/2 is selected in a BasicDateFilter(Filter pram) we should update our controls to match this data
Public Sub LoadFromFilter(ByVal Filter As i00BindingList.AdvancedBindingSource.BasicFilterBase) Implements i00BindingList.Plugins.iFilterPlugin.LoadFromFilter
Dim BasicDateFilter = TryCast(Filter, BasicDateFilter)
FireMonthCalendar_DateChanged = False
If BasicDateFilter IsNot Nothing Then
'we have an existing BasicDateFilter so load the control properties from that
LastBasicDateFilter = BasicDateFilter
MonthCalendar.SelectionRange = New SelectionRange(BasicDateFilter.DateFrom, BasicDateFilter.DateTo)
tsiSelectDate.Checked = True
Else
'this field is not filtered (at least not with a BasicDateFilter), so load the default values...
LastBasicDateFilter = Nothing
tsiSelectDate.Checked = False
End If
FireMonthCalendar_DateChanged = True
End Sub
Dim FireMonthCalendar_DateChanged As Boolean = True
Dim LastBasicDateFilter As BasicDateFilter
'When our MonthCalendar is updated raise the UpdateFilter event so that the Plugin can re-filter the data
Private Sub MonthCalendar_DateChanged(ByVal sender As Object, ByVal e As System.Windows.Forms.DateRangeEventArgs) Handles MonthCalendar.DateChanged, MonthCalendar.DateSelected
If FireMonthCalendar_DateChanged Then
Dim BasicDateFilter = New BasicDateFilter With {.DateFrom = MonthCalendar.SelectionRange.Start, .DateTo = MonthCalendar.SelectionRange.End}
If LastBasicDateFilter Is Nothing OrElse (BasicDateFilter.DateFrom <> LastBasicDateFilter.DateFrom OrElse BasicDateFilter.DateTo <> LastBasicDateFilter.DateTo) Then
RaiseEvent UpdateFilter(Me, New i00BindingList.Plugins.UpdateFilterPluginEventArgs() With {.FilterBase = BasicDateFilter})
LastBasicDateFilter = BasicDateFilter
tsiSelectDate.Checked = True
End If
End If
End Sub
'When the "Select a date or date range" option is checked call the MonthCalendar_DateChanged so that the Plugin can re-filter the data
Private Sub tsiSelectDate_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles tsiSelectDate.Click
tsiSelectDate.Checked = Not tsiSelectDate.Checked
LastBasicDateFilter = Nothing
If tsiSelectDate.Checked = True Then
'filter
MonthCalendar_DateChanged(MonthCalendar, New DateRangeEventArgs(MonthCalendar.SelectionRange.Start, MonthCalendar.SelectionRange.End))
Else
'unfilter
RaiseEvent UpdateFilter(Me, New i00BindingList.Plugins.UpdateFilterPluginEventArgs())
End If
End Sub
#End Region
End Class
The above code will produce the following:
Downloads
Total Downloads:
Downloads per day:
Change Log
20120723
- Fixed a bug that when canceling an edit (eg. in a DGV) on an existing row on the Binding List would delete the item!
20120719
- Made properties / functions etc of the BindingListView use T instead of object .. eg: Item(ByVal Index As Integer) As T
- AddRange added to BindingListView
- Added AddingFilterPlugin event to DataGridView that allows programmers to cancel the plugin from being loaded, or modify plugin settings
- Fixed a bug where the custom filter plugins would filter the data multiple times instead of just once
- Changed Filter Linq query structure to remove requirement for "From xItem in ..."
- Changed Filter Linq query structure so that you can just specify the fields with "[field]"
Thanks
Thanks for downloading.
Suggestions on possible improvements are much appreciated.