从 RowLeave 事件添加新行时出现异常

Exception when adding a new row from the RowLeave event

我有一个未绑定的 datagridview,设置允许用户添加行的选项为 True,我想要的是一旦我“完成”一行,datagridview 应该自动创建一个新的空行,所以我设置方法

DataGridView1.Rows.Add()

在 DataGridView1_Leave 事件中,但是一旦该行完成并出现异常: System.Windows.Forms.dll 中发生类型 'System.InvalidOperationException' 的未处理异常 - 无法在此事件处理程序中完成此操作 这是什么意思?应该是简单的代码,但我不知道如何解决

情况如下: 那就是接收者 DataGridView。当我在第一个空白行(由 AllowUserToAddRow = true 创建)并按 F3 时,将打开一个模态表单,其中包含另一个包含产品的 DataGridView select

这里是接收者 DataGridView 中 KeyDown 事件的代码

Private Sub DataGridView1_KeyDown(sender As Object, e As KeyEventArgs) Handles DataGridView1.KeyDown
    If e.KeyCode = Keys.F3 Then
        If frmZoomArticoli.ShowDialog = Windows.Forms.DialogResult.OK Then
                            Dim codart As String = frmZoomArticoli.DataGridView1.CurrentCell.Value.ToString()
            RicercaxCodiceArticolo(codart)
        End If
    End If
End Sub

这里是用 selected 产品填充收件人 DataGridView 的子 RicercaxCodiceArticolo(codart):

Private Sub RicercaxCodiceArticolo(ByVal codiceart As String)

    Dim strsql As String
    Dim cmd As SqlCommand
    Dim source As New BindingSource

    'Dichiariamo le variabili che ospitano i dati di riga
    Dim codice As String
    Dim descrizione As String
    Dim unitamisura As String
    Dim quantita As Double = 1.0
    Dim codiceiva As Double
    Dim costobase As Double
    Dim prezzobase As Double
    Dim costoultimo As Double
    Dim giacenza As Double
    Dim sconto1 As Double
    Dim sconto2 As Double

    connection.Open()
    strsql = "SELECT CODICEARTICOLO AS 'Codice', DESCRIZIONEARTICOLO AS 'Descrizione', UNITAMISURA AS 'Um', CODICEIVA AS 'Iva' " _
            & ", COSTOBASE AS 'Costo', PREZZOBASE AS 'Prezzo', SCONTO1 As 'Sc1', SCONTO2 As 'Sc2', COSTOULTIMO AS 'CostoUlt' " _
            & ", BARCODE AS 'Barcode', NOTEARTICOLO AS 'Note' ,CATEGORIAARTICOLO AS 'Categ.Art.', GIACENZA AS 'Giacenza' " _
            & ", FORNITOREPREF AS 'Fornit. Pref.' FROM Articoli " _
            & " WHERE CODICEARTICOLO = '" & codiceart & "'"

    cmd = New SqlCommand()
    cmd.CommandText = strsql
    cmd.CommandType = CommandType.Text
    cmd.Connection = connection
    source.DataSource = cmd.ExecuteReader()

    'Assegniamo i dati letti nel bindingsource alle variabili
    codice = source.Current!Codice
    descrizione = source.Current!Descrizione
    unitamisura = source.Current!Um
    codiceiva = Convert.ToDouble(source.Current!Iva)
    costobase = Convert.ToDouble(source.Current!Costo)
    prezzobase = Convert.ToDouble(source.Current!Prezzo)
    costoultimo = Convert.ToDouble(source.Current!Costoult)
    giacenza = Convert.ToDouble(source.Current!Giacenza)
    sconto1 = Convert.ToDouble(source.Current!Sc1)
    sconto2 = Convert.ToDouble(source.Current!Sc2)

    'Riempiamo le celle con i dati estratti dal BindingSource
    With DataGridView1.CurrentRow
        .Cells("grdCodice").Value = codice
        .Cells("grdDescrizione").Value = descrizione
        .Cells("grdUM").Value = source.Current!Um
        .Cells("grdQuantita").Value = quantita
        If TipoMovimento = "Carico" Then
            .Cells("grdPrezzoUnitario").Value = source.Current!CostoUlt
        Else
            .Cells("grdPrezzoUnitario").Value = source.Current!Prezzo
        End If
        .Cells("grdSconto1").Value = sconto1
        .Cells("grdSconto2").Value = sconto2
        .Cells("grdSconto3").Value = 0.0
        .Cells("grdSconto4").Value = 0.0
        'Per calcolare il prezzo totale di riga dobbiamo tenere presente le
        'informazioni che abbiamo gia' in anagrafica, ovvero il costo/prezzo
        'e gli sconti

        'Blocco di controllo sul tipo movimento
        If TipoMovimento = "Carico" Then
            If sconto1 > 0 Then
                .Cells("grdPrezzoTotale").Value = quantita * (costoultimo * (costoultimo * sconto1 / 100))
            Else
                .Cells("grdPrezzoTotale").Value = quantita * costoultimo
            End If
        ElseIf TipoMovimento = "Scarico" Then
            If sconto1 > 0 Then
                .Cells("grdPrezzoTotale").Value = quantita * (prezzobase * (prezzobase * sconto1 / 100))
            Else
                .Cells("grdPrezzoTotale").Value = quantita * prezzobase
            End If
        End If

        .Cells("grdAliquotaIva").Value = codiceiva
    End With

    connection.Close()

End Sub

这就是收件人 DataGridView 中的结果:

现在,假设我不想编辑 selected 行,因为我不需要编辑数量、价格或其他任何内容,但我只想插入一个新行继续插入其他产品。当我跳到行尾时我想创建一个新行,这就是为什么我在 DataGridView 的 RowLeave 事件中编写 DataGridView1.Rows.Add() 的原因,但这就是发生异常的地方: 很抱歉所有描述都是意大利语,但如果您需要任何其他详细信息,请随时询问。 如果我无能为力,剩下的就是在 DataGridView 外部添加一个按钮,从那里添加一个新行。欢迎任何其他解决方案。

您不使用 DataSource 网格有什么原因吗?然后你可以简单地将行添加到 DataSource.

如果您坚持手动添加行,那么您当前遇到的问题是代码永远不会向网格“添加”新行。该代码仅使用网格 CurrentRow 来设置值。这可能有效,但不会创建网格“新”行。

以这种方式使用网格 CurrentRow 是有问题的...因此,与其使用网格 CurrentRow,我建议您在 [= 中“添加”一个新行16=] 方法。像下面这样的东西应该添加新行,“new-new”空行应该在底部……

Dim newRowIndex As Int32
newRowIndex = DataGridView1.Rows.Add()
With DataGridView1.Rows(newRowIndex)
    .Cells("grdCodice").Value = codice
    .Cells("grdDescrizione").Value = descrizione
    '.....
End With