DataGridView中KeyPress事件处理器误绑定至非目标控件问题
解决DataGridView特定列输入限制被误应用到其他列的问题
问题根源
DataGridView采用编辑控件复用机制:整个控件只会维护一个编辑控件实例,切换不同列编辑时会重复使用这个控件。你之前仅在目标列添加KeyPress事件处理器,但未在切换到其他列时移除绑定,导致控件复用后,其他列的编辑操作也会触发限制逻辑。
解决方案
修改EditingControlShowing事件处理逻辑,先统一移除旧的事件绑定,再根据当前列是否为目标列设置控件属性和绑定事件,同时重置非目标列的控件默认属性:
Private Sub dgv_EditingControlShowing(sender As Object, e As DataGridViewEditingControlShowingEventArgs) Handles dgv.EditingControlShowing Dim tb As TextBox = DirectCast(e.Control, TextBox) ' 先移除之前绑定的KeyPress处理器,避免控件复用残留事件 RemoveHandler tb.KeyPress, AddressOf controlKeyPress ' 重置控件默认属性,消除目标列设置对其他列的影响 tb.CharacterCasing = CharacterCasing.Normal tb.MaxLength = 0 ' 0表示无长度限制,可根据实际需求调整 ' 判断当前列是否为目标列,是则设置属性并重新绑定事件 If dgv.CurrentCell.ColumnIndex = myColumn.Index Then tb.CharacterCasing = CharacterCasing.Upper tb.MaxLength = 10 AddHandler tb.KeyPress, AddressOf controlKeyPress End If End Sub Private Sub controlKeyPress(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Dim charEnum As Integer = CUInt(Microsoft.VisualBasic.Asc(e.KeyChar)) Dim tb As TextBox = DirectCast(sender, TextBox) Select Case charEnum Case 8 ' 允许退格键 Case 42 ' 仅允许在第一个位置输入星号 If tb.SelectionStart <> 0 Then e.KeyChar = "" Case 46 ' 不允许在第一个位置输入点,且第一个字符是星号时也禁止输入点 If tb.SelectionStart = 0 OrElse tb.Text.FirstOrDefault = "*" Then e.KeyChar = "" Case 65 To 90, 97 To 122 ' 第一个字符是星号时禁止输入字母 If tb.Text.FirstOrDefault = "*" Then e.KeyChar = "" Case Else ' 其他字符全部禁止 e.KeyChar = "" End Select End Sub
关键说明
- 先移除再绑定:每次触发
EditingControlShowing时先移除旧绑定,确保控件复用不会携带残留的事件处理器 - 重置控件属性:目标列设置的
CharacterCasing和MaxLength会保留在控件实例上,必须重置为默认值,避免影响其他列 - 统一处理所有列:无需单独针对某一列做移除操作,统一逻辑覆盖所有非目标列场景,更可靠稳定
内容的提问来源于stack exchange,提问作者Alan O'Brien
相关产品推荐
相关产品推荐

