65.9K
CodeProject 正在变化。 阅读更多。
Home

i00 BindingList 与 DataGridView

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.95/5 (20投票s)

2012 年 7 月 17 日

Ms-PL

4分钟阅读

viewsIcon

75656

易于使用的 BindingList 和 DataGridView, 支持高级 LINQ 过滤!

如果您在项目中使用它,请在下方留言告知。
简单的“我正在项目中使用它”就足够了。

引言

此项目旨在提供一种简单的方法来轻松地将数据添加到可过滤和排序的列表中……但(与我的大多数项目一样)它很快就发展到支持许多其他功能,例如完整的 LINQ 过滤、支持 UIEditors 的 DataGridView、过滤插件、具有过滤选项的 BindingNavigator 等等!

特点

BindingListView

  • 易于过滤
  • 易于排序
  • 支持 LINQ 过滤

DataGridView

  • 单元格上的 UI 类型编辑器绘制
  • 单元格编辑的 UI 类型编辑器支持
  • 内置列标题菜单,用于排序和过滤选项
  • 数据过滤插件
  • 过滤文本高亮显示
  • 比标准 DGV 更快
  • 图像缩放以适应单元格
  • 双击图像单元格即可选择图像
  • 轻松列出和允许选择 Enum 选项

BindingNavigatorWithFilter

  • 向标准 BindingNavigator 添加过滤字段

实现

要将 i00 BindingList 实现到您的项目中,首先执行以下任一操作:

  • i00BindingList 项目添加到您的解决方案并引用它(推荐)
  • 引用此项目输出的 i00BindingList.exe 文件
  • 或者,您可以将 zip 文件中的“i00BindingList”文件夹中的所有 *.vb 文件直接引入到您自己的项目中

创建绑定列表

绑定列表可以像任何 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)

过滤绑定列表

可以通过利用 i00BindingList.BindingListView.Filter 属性来过滤绑定列表。i00BindingList 过滤器采用 LINQ 编写,并支持直接调用您项目中的函数。例如,以下代码将过滤列表以显示所有出生于 1982 年的人

blPersons.Filter = "(Year([DOB]) = 1982)"

要访问您项目中的公共共享函数(在本例中为 PeopleFunctions.IsInFootballTeam()),您可以这样做:

blPersons.Filter = GetType(PeopleFunctions).FullName & ".IsInFootballTeam([Me]) = True"

注意:在使用过滤时,[Me] 和 [Fields]必须放在方括号内。

过滤绑定列表时,将调用 FilterChanged 事件。

绑定列表绑定

Binding List 公开了 BindingSource 属性,该属性可用作 DataGridViewDataSource,或用作 BindingNavigatorBindingSource

DataGridView

i00BindingList.DataGridView 继承自 DataGridView,可用于自定义数据源以支持 UIEditorsUIEditors 是 .NET Framework 的一部分,可自动为 i00 DataGridView 中的项目提供自定义编辑器,前提是网格的 AllowUIEditorCellsDrawUIEditorCells 属性均设置为 true。

在以下示例中,您可以看到 ColorEditor 的实际效果

有关创建自己的 UIEditor 的更多信息,请查看本文

DataGridView 的过滤插件

如果 i00BindingList.DataGridView 绑定到 i00BindingList.BindingListView,它将自动允许基于每列数据类型的标头进行过滤。这些可以扩展以通过插件提供高级过滤(如下图所示)

Filter plugins 是实现 i00BindingList.Plugins.iFilterPlugin 的类;它们会自动被拾取并允许根据每个字段的数据类型添加额外的过滤器。项目不需要引用插件(如果它们在外部文件中),但您需要将它们放在应用程序的路径中。

下载项目包含三个过滤器:ColorFilter(在 i00BindingList 项目中)、DateFilterRecentDateTimeFilter(在 Test 项目中)。

以下是实现 iFilterPlugin 及其用途的列表:

  • Public ReadOnly Property DataTypes() As System.Type() - 应设置为返回我们将用于此过滤器的(数组中的)数据类型。
  • Public ReadOnly Property Dispaly() As i00BindingList.Plugins.DisplayMethods - 设置何时显示此过滤器,选项包括 DefaultHide、Always、DefaultShow。
  • Public Sub LoadFromFilter(ByVal Filter As i00BindingList.AdvancedBindingSource.BasicFilterBase) - 在加载现有过滤器数据(BasicFilterBase)时调用,应相应地更新 MenuItems 中的控件。
  • Public Function MenuItems() As System.Collections.Generic.List(Of System.Windows.Forms.ToolStripItem) - 设置将加载到此过滤器菜单中的控件列表。
  • Public Event UpdateFilter(ByVal sender As Object, ByVal e As i00BindingList.Plugins.UpdateFilterPluginEventArgs) - 当您的控件导致过滤器更新时应引发此事件。

以下是一个用于过滤日期范围的 iFilterPlugin 示例:

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

上面的代码将生成以下结果:

下载次数

总下载次数:

每日下载量

更改日志

20120723

  • 修复了一个 bug:在 Binding List 中取消编辑现有行(例如在 DGV 中)会导致删除该项!

20120719

  • 将 BindingListView 的属性/函数等从 object 改为 T,例如:Item(ByVal Index As Integer) As T
  • 在 BindingListView 中添加了 AddRange
  • 向 DataGridView 添加了 AddingFilterPlugin 事件,允许程序员取消加载插件或修改插件设置
  • 修复了一个 bug:自定义过滤器插件会多次过滤数据而不是一次
  • 更改了 Filter Linq 查询结构,消除了对“From xItem in ...”的要求
  • 更改了 Filter Linq 查询结构,以便您只需指定字段,使用“[field]”即可

谢谢

感谢下载。

非常感谢关于可能改进的建议。

© . All rights reserved.