【问题标题】:How do I add a new row to a binding source如何将新行添加到绑定源
【发布时间】:2016-12-18 19:06:47
【问题描述】:

我正在尝试以编程方式将新行添加到绑定源。我知道调用 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

【问题讨论】:

  • 您可能应该在实际的底层数据源上工作 - DataView 只是其他事物(数据)的视图。

标签: vb.net datarow bindingsource datarowview


【解决方案1】:

'此例程采用 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 将 'always' 重新填充网格(包括使用 'Add/Delete/Modify 进行的任何更改)发送活动 '回到网格顶部

'我将着手解决这个问题,因为我已经完成了剩下的工作

【讨论】:

    【解决方案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
    

    【讨论】:

    • 我已经知道该项目是否已分离,但我缺少的部分是即使我使用了 BindingSource.AddNew() 方法,它也没有将新添加到数据表中,我必须添加该 DataRowView。行到 dataTable 然后它不再分离。 (一个理性的人会认为绑定源上的 AddNew 会自然而然地做到这一点。
    • 我刚刚在上次回复的末尾添加了额外的代码示例,看看是否有帮助。
    【解决方案3】:

    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() 。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多