在验证相同列和行中的先前 DataGridViewTextBoxCell 后设置新的 DataGridViewComboBoxCell

set new DataGridViewComboBoxCell for after validation of previous DataGridViewTextBoxCell in same column and row

我有这个 DataGridView 并且它有一个 DataGridViewTextBoxColumn 用户可以在其中键入数字,在他键入之后我执行搜索以查找该数字下的以前记录。

我想显示这些记录,以便用户可以 select 其中之一,或者保留键入的值,这意味着他想创建一个新记录。

为此,我想在用户完成输入时将每个 DataGridViewTextBoxCell 替换为 DataGridViewComboBoxCell 的那些选项。

但是,当我尝试执行此替换时引发此异常:"System.InvalidOperationException" in System.Windows.Forms.dll。附加信息:该操作无效,因为它会导致重新调用函数 SetCurrentCellAddressCore。

这是我的代码(我已经尝试处理 CellLeave 而不是 CellValidated):

Private Sub DataGridViewDebitos_CellValidated(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridViewDebitos.CellValidated
    DataGridViewDebitos.EndEdit(DataGridViewDataErrorContexts.Commit)
    If e.ColumnIndex = ColumnDebito.Index Then
        Dim cellDebito = DataGridViewDebitos.Rows(e.RowIndex).Cells(ColumnDebito.Index)
        Dim numDebito = String.Concat(If(cellDebito.Value, "").ToString.Where(Function(c) Char.IsLetterOrDigit(c)))
        If TypeOf cellDebito Is DataGridViewTextBoxCell AndAlso numDebito.Length >= 3 Then
            Dim prcsa As New List(Of JObject) 'In real version, prcsa is populated by an external function, but it doesn't affect the result
            Dim j = New JObject
            j.SetProperty("id", 0)
            j.SetProperty("nome", cellDebito.Value)
            prcsa.Insert(0, j) 'This option is always present, it allows user to keep simply what was typed
            'Exception hapens here
            DataGridViewDebitos(cellDebito.ColumnIndex, cellDebito.RowIndex) =
                New DataGridViewComboBoxCell With {
                    .DataSource = prcsa,
                    .DisplayMember = "nome",
                    .FlatStyle = FlatStyle.Flat,
                    .ValueMember = "id",
                    .Value = prcsa(0).Value(Of Integer)("id")}
        End If
    End If
End Sub

非常感谢

我已经通过 .BeginInvoke 将有问题的语句放入 Lambda 子程序中,这解决了问题,只是我不知道为什么...

谁能给我解释一下它的原理?谢谢!

Private Sub DataGridViewDebitos_CellValidated(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridViewDebitos.CellValidated
    DataGridViewDebitos.EndEdit(DataGridViewDataErrorContexts.Commit)
    If e.ColumnIndex = ColumnDebito.Index Then
        Dim cellDebito = DataGridViewDebitos.Rows(e.RowIndex).Cells(ColumnDebito.Index)
        Dim numDebito = String.Concat(If(cellDebito.Value, "").ToString.Where(Function(c) Char.IsLetterOrDigit(c)))
        If TypeOf cellDebito Is DataGridViewTextBoxCell AndAlso numDebito.Length >= 3 Then
            Dim prcsa As New List(Of JObject) 'In real version, prcsa is populated by an external function, but it doesn't affect the result
            Dim j = New JObject
            j.SetProperty("id", 0)
            j.SetProperty("nome", cellDebito.Value)
            prcsa.Insert(0, j) 'This option is always present, it allows user to keep simply what was typed
            'Exception hapens here
            DataGridViewDebitos.BeginInvoke(
                Sub()
                    DataGridViewDebitos(cellDebito.ColumnIndex, cellDebito.RowIndex) =
                        New DataGridViewComboBoxCell With {
                        .DataSource = prcsa,
                        .DisplayMember = "nome",
                        .FlatStyle = FlatStyle.Flat,
                        .ValueMember = "id",
                        .Value = prcsa(0)("id")}
                End Sub)
        End If
    End If
End Sub