如何实现即插即用DataGridView工具类:扩展Rows.Clear()保留筛选行
自定义带筛选行的DataGridView:仅扩展Rows.Clear()逻辑的即插即用方案
问题背景
我需要开发一个带筛选行的自定义DataGridView,作为现有程序中所有DataGridView的即插即用替代组件。要求原有常规行操作(如Rows.Add等)完全正常工作,但需要给Rows.Clear()添加额外逻辑——执行Clear后自动恢复筛选行。但Rows.Clear()无法直接重载,我尝试了以下方案:
Public Class dgv_with_filterrow Inherits DataGridView Private customRows As New CustomDataGridViewRowCollection(Me) Public Shadows ReadOnly Property Rows As CustomDataGridViewRowCollection Get Return customRows End Get End Property Public Overrides Sub Refresh() ' Add your custom implementation here Console.WriteLine("Custom Refresh() method called") ' Call the base class implementation MyBase.Refresh() End Sub ' Add other overridden methods as needed Public Class CustomDataGridViewRowCollection Inherits DataGridViewRowCollection Public Sub New(ByVal dataGridView As DataGridView) MyBase.New(dataGridView) End Sub ' Override the Clear method to provide custom behavior Public Overrides Sub Clear() ' Your custom implementation goes here Console.WriteLine("Custom Rows.Clear() method called") ' Call the base class implementation MyBase.Clear() End Sub End Class End Class
现有方案问题
上述代码的核心问题在于DataGridViewRowCollection的构造函数是**受保护(Protected)**的,无法直接实例化自定义的CustomDataGridViewRowCollection,导致除Clear外的其他行操作(如Rows.Add、Rows.Remove等)无法正常调用基类逻辑,引发功能异常。
解决方案:利用事件拦截+避免重写整个RowCollection
不需要自定义RowCollection,而是通过监听DataGridView的RowsCleared事件,在Clear操作完成后自动恢复筛选行;同时保证所有原生行操作不受影响。
最终实现代码
Public Class dgv_with_filterrow Inherits DataGridView ' 标记是否是内部触发的筛选行添加,避免循环触发 Private isReAddingFilterRow As Boolean = False Public Sub New() MyBase.New() ' 初始化时添加筛选行 AddFilterRow() ' 绑定RowsCleared事件,在Clear后恢复筛选行 AddHandler Me.RowsCleared, AddressOf OnRowsCleared End Sub ' 处理RowsCleared事件,在Clear完成后恢复筛选行 Private Sub OnRowsCleared(sender As Object, e As DataGridViewRowsClearedEventArgs) If Not isReAddingFilterRow Then isReAddingFilterRow = True ' 重新添加筛选行 AddFilterRow() isReAddingFilterRow = False End If End Sub ' 封装添加筛选行的逻辑 Private Sub AddFilterRow() ' 创建筛选行(示例:添加一行作为筛选行) Dim filterRow As New DataGridViewRow() ' 自定义筛选行的样式/内容,比如添加ComboBox、TextBox等控件 For Each col As DataGridViewColumn In Me.Columns Dim cell As DataGridViewCell = col.CellTemplate.Clone() cell.Value = "筛选..." ' 示例提示文本 filterRow.Cells.Add(cell) Next ' 将筛选行插入到第一行 Me.Rows.Insert(0, filterRow) ' 设置筛选行样式区分 filterRow.DefaultCellStyle.BackColor = Color.LightGray End Sub End Class
方案优势
- 即插即用:直接替换现有程序中的
DataGridView为dgv_with_filterrow即可生效,无需修改原有代码中的Rows.Add、Rows.Clear等调用 - 原生操作完全兼容:所有原生行操作(
Add、Remove、Insert等)保留原有逻辑,无需重写 - 精准扩展Clear逻辑:仅在
Rows.Clear()执行完成后自动恢复筛选行,其他操作不受干扰 - 绕过构造函数限制:无需自定义
DataGridViewRowCollection,避免了基类构造函数受保护的问题
关键说明
isReAddingFilterRow标记用于避免添加筛选行时再次触发RowsCleared事件,造成循环添加AddFilterRow方法可根据需求自定义筛选行的控件(比如添加下拉框、文本框等筛选组件)- 若需要在
Clear操作之前执行逻辑(如保存当前筛选条件),可新增Shadow覆盖的ClearRows方法,内部先执行前置逻辑再调用MyBase.Rows.Clear()
内容的提问来源于stack exchange,提问作者Ukkie
相关产品推荐
相关产品推荐

