将新记录粘贴到绑定的 DataGridView

Pasting new records to a Bound DataGridView

如果有人问过这个问题,我们深表歉意。如果是这样,我无法找到一个简单的解决方案。我试图允许用户在 DataGridView 中 copy/paste 多条记录(数据的内存副本,稍后当用户单击保存按钮时保存)并且找不到任何有效的东西。这可能是因为我对这一切有些不理解。

我使用 Visual Studio 的 drag/table 将标准编辑表单设置为一个表单,因此它使用了 BindingSource 控件和所有其他随之而来的控件。当手动在新行中逐条输入内容时,它工作得很好,因此它似乎设置正确,但是当涉及到使用代码添加记录(或多条记录)时,似乎没有任何效果。

我尝试了下面代码中概述的一些事情。有人可以至少引导我朝着正确的方向前进吗?粘贴多条记录不会那么难。

我 运行 当用户按下 Control-V 时(剪贴板正确保存分隔字符串):

Private Sub PasteClipboard()
    If Clipboard.ContainsText Then
        Dim sLines() As String = Clipboard.GetText.Split(vbCrLf)
        For Each sLine As String In sLines
            Dim Items() As String = sLine.Split(vbTab)

            Dim drv As DataRowView = AdjustmentsBindingSource.AddNew()
            drv.Item(1) = Items(0)
            drv.Item(2) = Items(1)
            drv.Item(3) = Items(2)
            drv.Item(4) = Items(3)
'Error on next line : Cannot add external objects to this list.
            AdjustmentsBindingSource.Add(drv)

        Next
    End If
End Sub

编辑

(bindingsource绑定了一个dataadapter,它绑定了一个mdb文件中的table,如果这样有助于理解的话)

我将代码的内部部分调整为:

            If (RowHasData(Items)) Then
                Dim drv As DataRowView = AdjustmentsBindingSource.AddNew()
                drv.Item("FontName") = Items(0)
                drv.Item("FontSize") = Items(1)
                drv.Item("LetterCombo") = Items(2)
                drv.Item("Adjustment") = Items(3)
                drv.Item("HorV") = Items(4)
            End If

它有点管用,但它还在 2 个新行之前添加了一个空白行。不确定这是从哪里来的,因为我什至包括了你的 RowHasData() 例程...

我认为“attemp3”应该有效,但是,尚不清楚 AdjustmentsBindingSource’s DataSource 是“什么”。是 List<T> 还是 DataTable

如果我将 BinngSource.DataSource 设置为 DataTable,则尝试 3 似乎有效。下面是一个有效的例子。

Private Sub PasteClipboard2()
    If Clipboard.ContainsText Then
        Dim sLines() As String = Clipboard.GetText.Split(vbCrLf)
        For Each sLine As String In sLines
            Dim Items() As String = sLine.Split(vbTab)
            If (RowHasData(Items)) Then
                Dim drv As DataRowView = AdjustmentsBindingSource.AddNew()
                drv.Item("FontName") = Items(0)
                drv.Item("FontSize") = Items(1)
                drv.Item("LetterCombo") = Items(2)
                drv.Item("Adjustment") = Items(3)
                drv.Item("HorV") = Items(4)
            End If
        Next
    End If
End Sub

这似乎在我的测试中有效。我添加了一个小函数 (RowHasData) 来避免格式​​错误的字符串导致问题。它只是检查大小(至少 5 个项目)并检查以确保一行实际上有“一些”数据。如果某行只是空字符串,则会被忽略。

Private Function RowHasData(items As String())
    If (items.Count >= 5) Then
        For Each item In items
            If (item <> "") Then Return True
        Next
    End If
    Return False
End Function

我猜想将新行“直接”添加到 BindingSourceDataSource. 中同样容易 在下面的示例中,代码是“直接”添加行到用作 DataSourceDataTableBindingSource. 我相信您可以通过简单地向列表添加一个新对象来对 List<T> 做同样的事情。下面是一个使用 BindingSourceDataTable 的完整示例。这只是将行添加到 table.

的底部
Dim gridTable1 As DataTable

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    PasteClipboard()
End Sub

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    gridTable1 = GetTable()
    FillTable(gridTable1)
    AdjustmentsBindingSource.DataSource = gridTable1
    AdjustmentsDataGridView.DataSource = AdjustmentsBindingSource
End Sub

Private Function GetTable() As DataTable
    Dim dt = New DataTable()
    dt.Columns.Add("FontName", GetType(String))
    dt.Columns.Add("FontSize", GetType(String))
    dt.Columns.Add("LetterCombo", GetType(String))
    dt.Columns.Add("Adjustment", GetType(String))
    dt.Columns.Add("HorV", GetType(String))
    Return dt
End Function

Private Sub FillTable(dt As DataTable)
    For index = 1 To 10
        dt.Rows.Add("Name_" + index.ToString(), "Size_" + index.ToString(), "Combo_" + index.ToString(), "Adjust_" + index.ToString(), "HorV_" + index.ToString())
    Next
End Sub

Private Sub PasteClipboard()
    If Clipboard.ContainsText Then
        Dim sLines() As String = Clipboard.GetText.Split(vbCrLf)
        Try
            Dim dataRow As DataRow
            For Each sLine As String In sLines
                Dim Items() As String = sLine.Split(vbTab)
                If (RowHasData(Items)) Then
                    dataRow = gridTable1.NewRow()
                    dataRow("FontName") = Items(0)
                    dataRow("FontSize") = Items(1)
                    dataRow("LetterCombo") = Items(2)
                    dataRow("Adjustment") = Items(3)
                    dataRow("HorV") = Items(4)
                    gridTable1.Rows.Add(dataRow)
                End If
            Next
        Catch ex As Exception
            MessageBox.Show("Error: " + ex.Message)
        End Try
    End If
End Sub

Private Function RowHasData(items As String())
    If (items.Count >= 5) Then
        For Each item In items
            If (item <> "") Then Return True
        Next
    End If
    Return False
End Function

希望代码对您有所帮助...

最后但重要的是,我只是猜测您可能没有“测试”用户可以“SELECT”数据的不同方式以及其他应用程序“如何”“复制”selected数据。我以前使用 WIN-OS“剪贴板”进行的测试有时会产生意想不到的结果。例如,如果用户 select 的多个项目使用“Ctrl”键“添加”到 selection,如果 selection 不连续,剪贴板中会出现额外的行。我的重点是使用 OS 剪贴板是古怪的恕我直言。我建议对用户可以 select 数据的“不同”方式进行大量测试。如果这不是问题,那么上面的代码应该可以工作。