DataGridView.RowLeave запускается перед кнопкой формы. MouseClick - PullRequest
0 голосов
/ 06 сентября 2018

Я ничего не могу найти об этом нигде: У меня есть форма с DataGridView и несколькими кнопками. Когда выбрана строка datagridview , и я нажимаю кнопку (на форме), dgv.RowLeave запускается раньше всего. Он срабатывает даже до щелчка или щелчка мыши.

Это имеет смысл, но проблема в том, что отправитель из RowLeave(ByVal sender As Object, ByVal e As DataGridViewCellEventArgs) - это DataGridView , а не кнопка. Поэтому в этот момент невозможно узнать, на какую кнопку нажали, потому что и отправитель, и e ссылаются на DataGridView, а не на форму или кнопки.

Событие 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

Ответы [ 3 ]

0 голосов
/ 07 сентября 2018

Я не уверен, как вы предотвращаете нажатие кнопки в вашем событии RowLeave, но я думаю, что вы должны использовать событие RowValidating для проверки DataGridView. Допустим, у нас есть DataGridView только с 1 столбцом и кнопкой. Проверка - это значение столбца, которое не должно превышать 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, проверка не будет запущена.

Порядок событий согласно этой ссылке такой:

Когда вы меняете фокус с помощью клавиатуры (TAB, SHIFT + TAB и и т. д.), вызывая методы Select или SelectNextControl или установка свойства ContainerControl.ActiveControl в текущий формы, события фокуса происходят в следующем порядке: Enter -> GotFocus -> Выйти -> Проверка -> Проверка -> LostFocus

Когда вы меняете фокус с помощью мыши или вызываете Фокус Метод фокусировки событий происходит в следующем порядке: Enter -> GotFocus -> LostFocus -> Оставить -> Подтвердить -> Подтвердить

0 голосов
/ 07 сентября 2018

Так есть ли способ узнать, где пользователь щелкнул, до того, как 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

Это немного сложное решение, но в событии DataGridView.RowLeave вы можете проверить, является ли свойство ContainerControl.ActiveControl , чтобы увидеть, является ли текущий активный элемент управления тот, который вы хотите проверить. В этом случае 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
0 голосов
/ 06 сентября 2018

Я использую WinForms здесь, но идея та же.

Итак, Event s привязаны к Control s.A Button - это Control, поэтому DataGridView.Затем в коде «позади» у вас есть 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);
}
...