我在任何地方都找不到任何相关内容:我有一个带有DataGridView
和一些按钮的表单。当选择了一行datagridview,然后单击一个按钮(在表单上)时,dgv.RowLeave
会在其他任何内容之前触发。它甚至在Click或MouseClick之前触发。
这是有道理的,但问题是RowLeave(ByVal sender As Object, ByVal e As DataGridViewCellEventArgs)
的发件人是DataGridView,而不是按钮。因此,在这一点上似乎不可能知道点击了什么按钮,因为sender和e都引用了DataGridView,而不是Form和Buttons。
触发Click事件,但仅在处理RowLeave之后触发。
那么有什么方法可以知道用户点击的位置,在RowLeave做其他事情之前(在我的情况下,导致Button.Click永远不会被处理),或者然后从RowLeave中?
Class MainForm
' The form contains a DataGridView and btnQuit (and other buttons)
Private Sub dgv_RowLeave(ByVal sender As Object, ByVal e As DataGridViewCellEventArgs) Handles dgv.RowLeave
ProgrammaticallyDoRowValidation(dgv.CurrentRow.Index) ' This does validation and more.
' But if btnQuit is clicked, I need to know here, or before RowLeave is
' triggered and NOT do this row validation.
' ...
End Sub
Private Sub Form_Click(sender As Object, e As EventArgs) Handles MyBase.Click
Dim frm As Form
frm = CType(sender, Form)
' Translated from Sach's comment below. Code never reaches this event
'(RowLeave prevents it).
End Sub
Private Sub Quit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnQuit.MouseClick
QuitPgm() ' Contains some more stuff.
' Also never executed, because RowLeave is handled first.
End Sub
End Class
我在这里使用WinForms
,但想法是一样的。
因此,Event
s与Control
s相关联。 Button
是Control
,DataGridView
也是如此。然后在Code Behind中你有Event Handlers
,它们本质上是与Control Events
相关的方法。
因此当你将一个Click
事件附加到一个按钮,幕后,VB.NET
创建一个像这样的Event Handler
:
private void button1_Click(object sender, EventArgs e)
{
}
现在sender
是一个对象,但它实际上是通过那里的DataGrid
。所以与你的陈述相反所以现在似乎不可能知道点击了什么按钮你知道是否点击了一个按钮。如果是,并且如果你附加了一个事件处理程序,它将被调用。例如,这将显示带有按钮文本的MessageBox
:
private void button1_Click(object sender, EventArgs e)
{
var btn = (Button)sender;
MessageBox.Show(btn.Text);
}
因此,如果您想知道是否单击了Form
,请附加Click
事件处理程序:
private void Form1_Click(object sender, EventArgs e)
{
var frm = (Form)sender;
MessageBox.Show(frm.Text);
}
我不确定你是如何阻止RowLeave事件中的按钮单击,但我认为你应该使用RowValidating事件来验证DataGridView。假设我们有一个只有1列和一个Button的DataGridView。验证是列值不得高于100.如果我们将验证放在RowValidating事件中,则在Leave事件之后但在Validated事件之前触发验证。如果验证失败,则不会触发子序列事件。
Public Class Form1
Function ProgrammaticallyDoRowValidation(i As Integer) As Boolean
If Convert.ToInt32(dgv(0, i).Value) > 100 Then
Return False
Else
Return True
End If
End Function
Private Sub dgv_RowValidating(sender As Object, e As DataGridViewCellCancelEventArgs) Handles dgv.RowValidating
If Not ProgrammaticallyDoRowValidation(dgv.CurrentRow.Index) Then
e.Cancel = True
End If
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
MessageBox.Show("Buton clicked")
End Sub
End Class
尝试运行代码并在列中输入大于100的值。您无法单击该按钮,因为它未通过验证。但是如果你将Button
的CausesValidation
属性设置为False
,则不会触发验证。
根据this link的事件顺序是这样的:
通过使用键盘(TAB,SHIFT + TAB等)更改焦点,通过调用Select或SelectNextControl方法,或通过将ContainerControl.ActiveControl属性设置为当前窗体,焦点事件按以下顺序发生:输入 - > GotFocus - >离开 - >验证 - >验证 - > LostFocus
当您使用鼠标或通过调用Focus方法更改焦点时,焦点事件按以下顺序发生:输入 - > GotFocus - > LostFocus - >离开 - >验证 - >验证
那么有什么方法可以知道用户点击的位置,在RowLeave做其他事情之前(在我的情况下,导致Button.Click永远不会被处理),或者然后从RowLeave中?
Private Sub dgv_RowLeave(ByVal sender As Object, ByVal e As DataGridViewCellEventArgs) Handles dgv.RowLeave ProgrammaticallyDoRowValidation(dgv.CurrentRow.Index) ' This does validation and more. ' But if btnQuit is clicked, I need to know here, or before RowLeave is ' triggered and NOT do this row validation. ' ... End Sub
这是一个kludge解决方案,但在DataGridView.RowLeave事件中,你可以检查ContainerControl.ActiveControl Property是否是你想要测试的当前活动控件。在这种情况下,ContainerControl
是Form
。
Private Sub dgv_RowLeave(ByVal sender As Object, ByVal e As DataGridViewCellEventArgs) Handles dgv.RowLeave
ProgrammaticallyDoRowValidation(dgv.CurrentRow.Index) ' This does validation and more.
' But if btnQuit is clicked, I need to know here, or before RowLeave is
' triggered and NOT do this row validation.
' ...
If Me.ActiveControl Is btnQuit Then
' do something
End If
End Sub