1

我正在尝试以编程方式将新行添加到绑定源。我知道调用 bsSource.AddNew() 会添加一个新行,我将其转换为 DataRowView 并设置我的值。我的问题是 - DataRowView.Row 显示分离的 RowState。我不希望它被分离;我相信它应该显示已添加 - 我也不希望它将更改提交到数据库(这是有充分理由的)。我想稍后再选时间。我的代码如下:

private Sub AddToRelationSource(binID As Integer, gradeID As Integer, IsChecked As Boolean)
            Dim drv As DataRowView = DirectCast(bsBinGrades.AddNew(), DataRowView)


            drv.Row("IsSelected") = IsChecked
            drv.Row("BinID") = binID
            drv.Row("GradeID") = gradeID
    ' I tried drv.EmdEdit(0 drv.Row.EndEdit() - Row State still shows detached

End Sub
4

3 回答 3

6

BindingSource AddNew 方法实际上并没有将新记录添加到底层数据源,它只是将它作为分离项添加到绑定源。当使用数据表作为数据源时,我需要获取数据表并使用 AddRow() 方法 - 这会正确地将我的 bindingsource 中的值设置为添加,以便在 bindingsource.Update() 方法上将更改提交到数据库。

我使用的代码:

    Dim drv As DataRowView = DirectCast(bsData.AddNew(), DataRowView)

    drv.BeginEdit()

    drv.Row.BeginEdit()

    drv.Row("IsSelected") = IsChecked

    drv.Row.EndEdit()

    drv.DataView.Table.Rows.Add(drv.Row)

最后一行是将项目实际添加到数据源的内容 - 我误解了 BindingSource.AddNew() 。

于 2016-08-15T14:08:43.147 回答
2

以下可能是正确的方向。首先,我使用了一些语言扩展方法,例如

Public Module BindingSourceExtensions
    <Runtime.CompilerServices.Extension()>
    Public Function DataTable(ByVal sender As BindingSource) As DataTable
        Return CType(sender.DataSource, DataTable)
    End Function
    <Runtime.CompilerServices.Extension()>
    Public Sub AddCustomer(ByVal sender As BindingSource, ByVal FirstName As String, ByVal LastName As String)
        sender.DataTable.Rows.Add(New Object() {Nothing, FirstName, LastName})
    End Sub
    <Runtime.CompilerServices.Extension()>
    Public Function DetachedTable(ByVal sender As BindingSource) As DataTable
        Return CType(sender.DataSource, DataTable).GetChanges(DataRowState.Detached)
    End Function
    <Runtime.CompilerServices.Extension()>
    Public Function AddedTable(ByVal sender As BindingSource) As DataTable
        Return CType(sender.DataSource, DataTable).GetChanges(DataRowState.Added)
    End Function
End Module

现在将 ID、FirstName 和 LastName 加载到 DataTable 中,Datatable 成为 BindingSource 的 DataSource,后者是 BindingNavigator 的 BindingSource,并连接到 DataGridView。

为了简单起见,我模拟了数据,没有断言,例如确保我们有有效的名字和姓氏,而是专注于方法。

首先使用扩展方法向 BindingSource 的底层 DataTable 添加一行。

bsCustomers.AddCustomer("Karen", "Payne")

现在检查是否有分离或添加的行

Dim detachedTable As DataTable = bsCustomers.DetachedTable
If detachedTable IsNot Nothing Then
    Console.WriteLine("Has detached")
Else
    Console.WriteLine("No detached")
End If
Dim AddedTable As DataTable = bsCustomers.AddedTable
If AddedTable IsNot Nothing Then
    Console.WriteLine("Has added")
Else
    Console.WriteLine("None added")
End If

由于我们没有与数据库表对话,因此主键没有按预期更新,并且由于您不想更新数据库表,这很好。当然,如果您在项目后期需要,有一种方法可以获取新添加记录的主键。

添加

Private Sub BindingSource1_AddingNew(ByVal sender As System.Object, ByVal e As System.ComponentModel.AddingNewEventArgs) Handles BindingSource1.AddingNew
  Dim drv As DataRowView = DirectCast(BindingSource1.List, DataView).AddNew()
  drv.Row.Item(0) = "some value"
  e.NewObject = drv
  ' move to new record
  'BindingSource1.MoveLast()
End Sub
于 2016-08-12T01:05:20.580 回答
0

'这个例程使用用户填写的各种字段的 AddForm 并调用 TableAdapter 的 Insert 方法。'完成后,再将表格反映回'各种组件。

Private Sub AddRecord()
    'The following line did not work because I could not get
    'the bs definition down.
    'Tried the BindingSource but in gave an error on 
    'DataRowView so I came up with an alternate way of 
    'adding the row.
    'Dim drv As DataRowView = DirectCast(bsData.AddNew(), DataRowView)
    'Dim drv As DataRowView = DirectCast(RecTableBindingSource.AddNew(), DataRowView)

    'drv.BeginEdit()
    'drv.Row.BeginEdit()
    'drv.Row("Title") = "Order, The"
    'drv.Row.EndEdit()
    'drv.DataView.Table.Rows.Add(drv.Row)

    RecTableTableAdapter.Insert(pAddForm.tTitle.Text,
                                pAddForm.tCast.Text,
                                pAddForm.tAKA.Text,
                                pAddForm.tRelated.Text,
                                pAddForm.tGenre.Text,
                                pAddForm.tRated.Text,
                                pAddForm.tRelease.Text,
                                pAddForm.tLength.Text)

    Validate()
    RecTableBindingSource.EndEdit()
    RecTableTableAdapter.Update(VideoDBDataSet.RecTable)
    RecTableAdapterManager.UpdateAll(VideoDBDataSet)
    RecTableTableAdapter.Fill(VideoDBDataSet.RecTable)
    VideoDBDataSet.AcceptChanges()
End Sub

'Here is my Delete Record routine
Private Sub DeleteRecordToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles DeleteRecordToolStripMenuItem.Click
    Dim RowIndex As Int32

    If (dgvRec.SelectedRows.Count > 0) Then
        RowIndex = dgvRec.SelectedRows(0).Index
        'Now we have to delete the record
        dgvRec.Rows.RemoveAt(RowIndex)

        dgvRec.CommitEdit(RowIndex)
        dgvRec.EndEdit()
        Validate()
        RecTableBindingSource.EndEdit()
        RecTableTableAdapter.Update(VideoDBDataSet.RecTable)
        RecTableAdapterManager.UpdateAll(VideoDBDataSet)
        RecTableTableAdapter.Fill(VideoDBDataSet.RecTable)
        VideoDBDataSet.AcceptChanges()
    Else
        'No row selected to work with
    End If
End Sub

'The pAddForm MUST be open for this routine to work
Private Sub UpdateGridFromForm()
    Dim RowIndex As Int32
    Dim Index As Int32
    Dim RecIndex As Int32
    Dim dt As DataTable

    If ((pAddForm Is Nothing) = False) Then
        RowIndex = pAddForm.GridIndex
        If (RowIndex >= 0) Then
            Index = pAddForm.Index
            If (Index = dgvRec.Rows(RowIndex).Cells(constRecGridColIndex).Value) Then
                'OK, we have a match so we are good to go
                Call PopulateGridFields(RowIndex)
            Else
                MsgBox("Unable to save data back to the Grid because the record is no longer the same")
            End If
        Else
            'This must be a NEW record
            Call AddRecord()
        End If
    Else
        'No form to work with
    End If
End Sub

'Populate the dgvRec fields from pAddForm
Private Sub PopulateGridFields(RowIndex As Int32)
    dgvRec.Rows(RowIndex).Cells(constRecGridTitle).Value = pAddForm.tTitle.Text
    dgvRec.Rows(RowIndex).Cells(constRecGridCast).Value = pAddForm.tCast.Text
    dgvRec.Rows(RowIndex).Cells(constRecGridAKA).Value = pAddForm.tAKA.Text
    dgvRec.Rows(RowIndex).Cells(constRecGridRelated).Value = pAddForm.tRelated.Text
    dgvRec.Rows(RowIndex).Cells(constRecGridGenre).Value = pAddForm.tGenre.Text
    dgvRec.Rows(RowIndex).Cells(constRecGridRated).Value = pAddForm.tRated.Text
    dgvRec.Rows(RowIndex).Cells(constRecGridRelease).Value = pAddForm.tRelease.Text
    dgvRec.Rows(RowIndex).Cells(constRecGridLength).Value = pAddForm.tLength.Text

    dgvRec.CommitEdit(RowIndex)
    dgvRec.EndEdit()
    Validate()
    RecTableBindingSource.EndEdit()
    RecTableTableAdapter.Update(VideoDBDataSet.RecTable)
    RecTableAdapterManager.UpdateAll(VideoDBDataSet)
    RecTableTableAdapter.Fill(VideoDBDataSet.RecTable)
    VideoDBDataSet.AcceptChanges()
End Sub

'这一切都很好。
'我现在唯一的问题是 DataGridView 将'总是'重新填充网格(包括使用'添加/删除/修改的任何更改)将活动的'行发送回网格的顶部

'我将努力解决这个问题,因为我有剩下的工作

于 2021-09-06T15:51:22.037 回答