关于datagridview:在选择DataGridViewCell /在VB.Net中获得焦点时进行检测

Detect when DataGridViewCell is Selected/Gains Focus in VB.Net

在我正在从事的项目中,我创建了一个屏幕键盘,该键盘可以键入TextBoxes或DataGridViewCells。

我尝试完成此操作的方法是使用一些方法和变量。首先,有一个名为CurrentFocus的全局变量,该变量是一个对象,可以设置为键盘可以键入的具有最新焦点的任何对象。之所以创建此变量,是因为VB.Net中似乎没有LastFocus样式方法。

我通过将简单的事件处理程序添加到将要以以下方式键入数据的文本框中来设置CurrentFocus的值:

1
2
3
4
5
6
Dim randomTextbox As New Textbox
AddHandler randomTextbox.GotFocus, AddressOf TextboxGainsFocus

Private Sub TextboxGainsFocus(sender as Textbox, e As EventArgs)
    CurrentFocus = sender
End Sub

至于输入文本框本身,键盘上的每个键都调用以下方法,参数值是所按下的任何键的大写字母(因此,按下" B"键将发送" B"作为参数)

1
2
3
4
5
6
7
8
9
10
11
12
13
Private Sub KeypadPress(ByCal key As Char)
    If TypeOf CurrentFocus Is TextBox Then
        If Char.IsDigit(key) Then
            CType(CurrentFocus, Textbox).Text &= key
        Else
            If shiftActive Then
                CType(CurrentFocus, Textbox).Text &= key
            Else
                CType(CurrentFocus, Textbox).Text &= Char.ToLower(key)
            End If
        End If
    End If
End Sub

我没有一种方法可以轻松地设置您按住的Shift键,因此我将" Shift"设置为类似于Caps Lock,只需打开或关闭它即可。这就是shiftActive布尔值的目的。

现在,以上所有代码都可以正常工作。我现在的问题是我无法使其与DataGridViewCells一起使用。首先,我尝试将类似的EventHandler添加到我正在使用的数据网格中

1
2
3
4
5
6
Dim randomGrid As New DataGridView
AddHandler randomGrid.GotFocus, AddressOf GridGainsFocus

Private Sub GridGainsFocus(sender As DataGridView, e As EventArgs)
    CurrentFocus = sender.CurrentCell
End Sub

我尝试将ElseIf案例添加到KeypadPress方法中,以检测CurrentFocus是DataGridViewCell的时间。很好我的问题是,要么没有选择正确的单元格,要么什么都不做。

例如,假设我的DataGridView中有3行3列。我选择单元格(2,2),然后按键盘上的一个键。如果我插入一个断点以查看KeypadPress方法触发时CurrentFocus的值是什么,它将显示CurrentFocus为Cell(0,0)。

不过,这并不总是会发生。有时我确实将它随机地(并且看起来确实是随机的)设置为适当的单元格,但是尝试类似

1
CType(CurrentFocus, DataGridViewCell).Value &= key

在我的Keypress方法中,什么都不做来更改DataGridViewCell的值。

那我到底需要做什么?有没有一种方法可以将每个Cell设置为拥有自己的处理程序,并以这种方式工作?我该如何做才能修改单元格本身的值?

感谢您的协助。


所以我想出了解决问题的方法,以后我将逐步为有此问题的任何人解决这个问题。

首先,我向DataGridView添加了一个事件处理程序,该事件处理程序的工作方式类似于我的文本框的事件处理程序。

1
2
3
4
5
6
Dim exGrid As DataGridView
AddHandler exGrid.CellEnter, AddressOf GridGainsFocus

Private Sub GridGainsFocus(sender As DataGridView, e As EventArgs)
    CurrentFocus = sender.CurrentCell
End Sub

这种工作方式是DataGridViewCells无法获得Focus。只有DataGridView本身才能获得焦点。而是当单元格被"聚焦"时,它们自身被设置为"选定"。因此,您需要使用CellEnter事件,该事件在用户选择单元格时触发。现在进入我的Keypress方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Private Sub KeypadPress(ByVal key As Char)
    If TypeOf CurrentFocus Is TextBox Then
        Me.ActiveControl = CurrentFocus
        If Char.IsDigit(key) Then
            SendKeys.SendWait(key)
        Else
            If shiftActive Then
                SendKeys.SendWait(key)
            Else
                SendKeys.SendWait(Char.ToLower(key))
            End If
        End If
    ElseIf TypeOf CurrentFocus Is DataGridViewCell Then
        If CType(CurrentFocus, DataGridViewCell).ReadOnly = False THen
            If Char.IsDigit(key) Then
                If CType(CurrentFocus, DataGridViewCell).Value.Equals(0) Then
                    CType(CurrentFocus, DataGridViewCell).Value = key
                Else
                    CType(CurrentFocus, DataGridViewCell).Value &= key
                End If
            End If
        End If
    End If
End Sub

因此,我将从上至下进行讨论。首先,您会注意到我在尝试向TextBox中输入数据时修改了用于处理按键的代码。这是因为对于我的TextBox,我将它们设置为具有"自动完成"数据以帮助搜索数据。我在原始问题中提出的第一个设置不允许使用"自动完成"数据,因为没有触发任何实际的按键。

因此,通过更改,我现在执行了以下操作:

  • 当按下按钮时,如果CurrentFocus对象的类型为TextBox,则它将当前焦点更改为该对象。
  • 触发SenKey事件。这将触发TextBox自动完成。
  • 现在用于DataGridViewCells。当我使用GridGainsFocus方法将CurrentFocus对象设置为DataGridViewCell时,该对象将存储对该单元的完美引用。所以我要做的就是修改那个Cell的值。

    现在,出于程序目的,我只希望用户将数字值放入单元格中,因此这就是为什么要使用IsDigit if语句的原因。特定的If value.Equals(0)设置为当单元格中的默认值为0时,单击" 5"键不会将文本输入设置为" 05",而是设置为" 5"。