AddNew(),删除此行时出现问题

AddNew(), problems deleting this row

我有一个绑定到 BindingSource 的 DataGridView。然后我有一个按钮来添加新记录:

Private Sub btnNew_Click(sender As Object, e As EventArgs) Handles btnNew.Click
    _bsStaff.AddNew()
End Sub

这确实创建了一个新行,其后还有 "next new/blank" 行。这工作正常,除非我立即按下删除按钮尝试删除这个新添加的行:

Private Sub btnDelete_Click(sender As Object, e As EventArgs) Handles btnDelete.Click
    If MessageBox.Show("Delete staff member record?", "Confirm", MessageBoxButtons.YesNo, _
                       MessageBoxIcon.Question) = Windows.Forms.DialogResult.Yes Then
        _bsStaff.RemoveCurrent()
    End If
End Sub

这会删除新行,但也会删除之前的行!

我尝试在 RemoveCurrent、_bsStaff.EndEdit()If _bsStaff.Position + 1 = _bsStaff.Count Then 之前添加一行,但问题仍然存在。

有人可以解释这种行为并提供解决方案吗?


已添加:我以为我用这段代码打败了它,检查行状态:

Private Sub btnDelete_Click(sender As Object, e As EventArgs) Handles btnDelete.Click

    Dim state = CType(_bsStaff.Current, DataRowView).Row.RowState
    Select Case state
        Case DataRowState.Added
            _bsStaff.RemoveCurrent()
        Case DataRowState.Deleted
            MessageBox.Show("Row already deleted.", "Delete")
        Case DataRowState.Detached
            _bsStaff.CancelEdit()
        Case DataRowState.Modified
            If MessageBox.Show("Delete staff member record?", "Confirm", MessageBoxButtons.YesNo, _
                               MessageBoxIcon.Question) = Windows.Forms.DialogResult.Yes Then
                _bsStaff.RemoveCurrent()
            End If
        Case DataRowState.Unchanged
            If _bsStaff.Position + 1 > _bsStaff.Count Then
                'do nothing, the new row
            ElseIf MessageBox.Show("Delete staff member record?", "Confirm", MessageBoxButtons.YesNo, _
                               MessageBoxIcon.Question) = Windows.Forms.DialogResult.Yes Then
                _bsStaff.RemoveCurrent()
            End If
        Case Else
            'do nothing
    End Select
End Sub

不过,看截图,

当我点击进入新行,然后点击我的按钮时,它处于未更改状态,但它是具有当前记录指针的前一行(未更改状态可能指的是),它是否要删除这一行。

本质上,我想我需要一种方法来检测新行刚刚被点击进入,但没有输入任何内容,这样我就可以放弃删除的尝试。

我将 post 我目前的解决方案作为一个提议但不太情愿的答案,希望它能鼓励有人用更专业的解决方案来打败我。

我目前采取务实的方法,明确告诉用户他们将要删除哪条记录:

Private Sub btnDelete_Click(sender As Object, e As EventArgs) Handles btnDelete.Click
    Dim currentRow = CType(_bsStaff.Current, DataRowView).Row
    Dim sMemberMessage As String

    Dim state = currentRow.RowState
    Select Case state
        Case DataRowState.Added
            _bsStaff.RemoveCurrent()
        Case DataRowState.Deleted
            MessageBox.Show("Row already deleted.", "Delete")
        Case DataRowState.Detached
            _bsStaff.CancelEdit()
        Case DataRowState.Modified, DataRowState.Unchanged
            sMemberMessage = String.Format("Delete record ({0} {1} {2}) ?", _
                    _bsStaff.Current("StaffID"), _bsStaff.Current("FirstName"), _bsStaff.Current("LastName"))
            If MessageBox.Show(sMemberMessage, "Confirm", MessageBoxButtons.YesNo, _
                               MessageBoxIcon.Question) = Windows.Forms.DialogResult.Yes Then
                _bsStaff.RemoveCurrent()
            End If
        Case Else
            'do nothing
    End Select
End Sub

人们会认为,如果有人只是点击进入新行,他们就会点击离开它,但因为它会立即插入一个增量值并选择一个部门,所以可以理解为什么他们会被鼓励去单击删除按钮。

(一定有某种方法可以检测行是否处于这种异常的、容易发生的状态。)

同时,为了进行比较和评论(和批评),我将 post 我的第二个改进的解决方案放在这里。

这是我当前的 Delete 方法的完整代码块:

Private Sub btnDelete_Click(sender As Object, e As EventArgs) Handles btnDelete.Click
    If _bsStaff.Current Is Nothing Then
        Exit Sub        'nothing to consider deleting
    End If
    Dim currentRow = CType(_bsStaff.Current, DataRowView).Row
    Dim sMemberMessage As String

    Dim state = currentRow.RowState
    Select Case state
        Case DataRowState.Added
            'newly added, just remove it
            _bsStaff.RemoveCurrent()
        Case DataRowState.Deleted
            MessageBox.Show("Row already deleted.", "Delete")
        Case DataRowState.Detached
            _bsStaff.CancelEdit()
        Case DataRowState.Modified, DataRowState.Unchanged
            If dgvStaff.SelectedCells.Count > 0 AndAlso _
                    dgvStaff.SelectedCells(0).RowIndex = dgvStaff.NewRowIndex Then
                'a new, blank, row, is attempted to be deleted
                '(the current row is the one before this)
                _bsStaff.CancelEdit()
                Exit Sub
            End If
            sMemberMessage = String.Format("Delete record ({0} {1} {2}) ?", _
                    _bsStaff.Current("StaffID"), _bsStaff.Current("FirstName"), _bsStaff.Current("LastName"))
            If MessageBox.Show(sMemberMessage, "Confirm", MessageBoxButtons.YesNo, _
                               MessageBoxIcon.Question) = Windows.Forms.DialogResult.Yes Then
                _bsStaff.RemoveCurrent()
            End If
        Case Else
            'do nothing
    End Select
End Sub

关键组件在这里:

        Case DataRowState.Modified, DataRowState.Unchanged
            If dgvStaff.SelectedCells.Count > 0 AndAlso _
                    dgvStaff.SelectedCells(0).RowIndex = dgvStaff.NewRowIndex Then
                'a new, blank, row, is attempted to be deleted
                '(the current row is the one before this)
                _bsStaff.CancelEdit()
                Exit Sub
            End If

看我问题的截图,虽然当前行是新行的正上方,但新行中还有一个SelectedCell。使用 dgvStaff.SelectedCells(0).RowIndex = dgvStaff.NewRowIndex 我确认此单元格位于新的(空白)行中。现在 只有 如果用户点击了这个新行,它就会处于 Unchanged 状态,并立即按下删除按钮,这是准确的我正在尝试检测的情况。如果他们在这个新行中输入了任何内容,那么它将不再是新行(不满足测试条件),也不会处于未更改的状态。在这些情况下,较早的情况已经导致该行被放弃。

它有点笨拙(我仍然希望对此有所改进)但这也是我试图捕捉的一个非常具体的情况。