将选定的复选框行从DGV复制到DGV2,包括图像列

时间:2019-01-22 16:22:53

标签: vb.net image winforms datagridview

我目前正在尝试将选定的行从一个DataGridView复制到另一个。 我正在尝试捕获CheckBox的值,如果选中它,那么整行将被复制到另一个DataGridView。
例如,像添加到购物车然后查看购物车。我提到了以下帖子:
Copy selected datagridrow to new datagridview on different form

但是似乎没有帮助。
我已经尝试过使用For循环,例如下面的循环,但是我不确定如何进行此循环。

Private Sub btnAdd_Click(sender As Object, e As EventArgs) Handles btnAdd.Click
    Dim dt As New DataTable()
    AppendColumnsToDGV2()
    For Each row As DataGridViewRow In DataGridView1.Rows
        If row.Cells("SelectColumn").Value = True Then
            Dim NewRow As DataRow
            For i As Integer = 0 To row.Cells.Count - 1
                NewRow(i) = row.Cells(i).Value
                DataGridView2.Rows.Add(NewRow)
            Next
        End If
    Next

AppendColumnsToDGV2

  Private Sub AppendColumnsToDGV2()
      Dim dt As New DataTable
      'dt.Columns.Add(CreateDGVCheckBoxCol())
      'dt.Columns.Add(CreateImageColumn())
      dt.Columns.Add(DataGridView1.Columns(3).HeaderText)
      dt.Columns.Add(DataGridView1.Columns(4).HeaderText)
      dt.Columns.Add(DataGridView1.Columns(5).HeaderText)
      dt.Columns.Add(DataGridView1.Columns(6).HeaderText)
      DataGridView2.DataSource = dt
End Sub

我在这里做的没有用,我也不知道该怎么办。
任何帮助将不胜感激,谢谢。

每当我运行此代码时,都会出现错误:

  

System.NullReferenceException:对象引用未设置为实例   一个对象

我不确定该如何解决。

这是DataGridView的样子:

WhatDGVLooksLike

3 个答案:

答案 0 :(得分:5)

这个问题与上一个问题严格相关:
Display images in a DataGridView column using JSON objects as DataSource

您正在使用 Result 的子类( RootObject )来填充第一个DataGridView。

修改 Result 类,如下所示:

  • 添加一个新属性, Selected As Boolean ,该属性以 <JsonIgnore> 属性装饰。
  • 在此处添加一个名为 SelectionResult 的新子类,并选择您认为需要的 Result 类的属性。第二个DataGridView显示选定的产品。
  • Result 类添加一个复制方法,该方法将自身的子节作为 SelectionResult 对象返回。

Public Class Result
    <JsonIgnore>
    Public Property Selected As Boolean

    '(...)

    Public Function GetSelectionResult() As SelectionResult
        Return New SelectionResult With {
            .ID = Me.id,
            .Image = Me.Image,
            .Name = Me.Name,
            .ProductDescription = Me.ProductDescription,
            .Department = Me.Department,
            .Price = Me.Price,
            .Unitprice = Me.Unitprice
        }
    End Function
End Class

Public Class SelectionResult
    Public Property ID As Integer
    Public Property Image As Bitmap
    Public Property Name As String
    Public Property ProductDescription As String
    Public Property Department As String
    Public Property Price As Decimal
    Public Property Unitprice As Decimal
End Class
  • 在表单中添加两个List(Of Class)作为字段。在上一个问题中,主类称为 ProductsQuery ,因此我重新使用了已在此处定义的名称:

Private CurrentProducts As List(Of ProductsQuery.Result) = New List(Of ProductsQuery.Result)()
Private SelectedProducts As List(Of ProductsQuery.SelectionResult) = New List(Of ProductsQuery.SelectionResult)()
  • 在填充第一个DataGridView的方法中,初始化 CurrentProducts 列表:

    CurrentProducts = New List(Of ProductsQuery.Result)()
    
  • 反序列化JSON之后,用JSON结果填充列表:

    CurrentProducts.AddRange(JsonPost.uk.ghs.Products.Results)
    

在将所选产品添加到第二个DataGridView的Button的事件处理程序中,插入以下代码:

修改
SelectedProducts列表保留在第一个DataGridView中选择的项目:仅将 CurrentProducts 列表中尚未存在的项目添加到选择中。

btnRemoveSelection 按钮从SelectedProducts列表中删除第二个DataGridView中的选定项。 DataGridView行的选择有些麻烦,因此可能要添加一个CheckBox Column来简化要删除项目的选择。

Private Sub btnAdd_Click(sender As Object, e As EventArgs) Handles btnAdd.Click
    SelectedProducts.AddRange(CurrentProducts.
                       Where(Function(p) p.Selected = True AndAlso
                             (Not SelectedProducts.Any(Function(sp) sp.ID = p.id))).
                       Select(Function(p) p.GetSelectionResult()).ToArray())
    ResetCart()
End Sub

Private Sub btnRemoveSelection_Click(sender As Object, e As EventArgs) Handles btnRemoveSelection.Click
    If DataGridView2.SelectedRows.Count = 0 Then Return

    Dim itemsRemoved As Boolean = False
    Dim selectedItems() As Integer = DataGridView2.SelectedRows.
                                     OfType(Of DataGridViewRow)().
                                     Select(Function(r) CInt(r.Cells("ID").Value)).ToArray()
    For Each ID As Integer In selectedItems
        Dim currentIndex As Integer = SelectedProducts.FindIndex(Function(p) p.ID = ID)
        If currentIndex >= 0 Then
            SelectedProducts.RemoveAt(currentIndex)
            itemsRemoved = True
        End If
    Next
    If itemsRemoved Then
        ResetCart()
    End If
End Sub

Private Sub ResetCart()
    DataGridView2.DataSource = Nothing
    DataGridView2.DataSource = SelectedProducts
    DataGridView2.Columns(0).Visible = False
    DataGridView2.AutoResizeRows()
End Sub

这用第一个DataGridView的选定元素填充 List(Of SelectedProducs) ,并将第二个DataGridView的DataSource设置为此列表。

请注意,DataGridView的第一列设置为Visible = False,因为该列对应于所选元素的 ID 属性

GetSelectionResult() 类的 Result 返回在 SelectionResult中定义的属性值< / strong>类。您当然可以重新定义此类,以包含您认为合适的任何属性。


这是这些修改的结果:

DataGridView JSON results

答案 1 :(得分:2)

如果您正确绑定了数据,则单击该复选框时,基础数据将更新。然后,您可以只使用一些LINQ。您应该避免在任何可能的地方(在可能的情况下)对DataGridViewRows进行迭代,因为它们不应该保存数据,而应该显示数据。

这个简单的示例在vb.net中以具有两个DataGridViews和一个具有默认名称的Button的形式工作。

Public Class Form1

    Private allProducts As List(Of Product)
    Private basketProducts As List(Of Product)

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        allProducts = New List(Of Product) From {
                New Product() With {.Name = "Fairy Gel", .ID = 1},
                New Product() With {.Name = "Fairy Caps", .ID = 2},
                New Product() With {.Name = "Fairy Liquid", .ID = 3}}
        DataGridView1.DataSource = allProducts
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        basketProducts = allProducts.Where(Function(p) p.Selected).ToList()
        DataGridView2.DataSource = basketProducts
    End Sub

    ' dummy class to emulate your data
    Private Class Product
        Public Property Selected As Boolean
        Public Property Name As String
        Public Property ID As Long
    End Class

End Class

enter image description here

答案 2 :(得分:0)

您当前正在使用2个单独的数据表。另外,您每次设置列值时都试图添加行。这可能对您有用。

DWORD dwEventMask, dwIncommingReadSize;
int dwSize=0;
char szBuf[10];
if(!SetCommMask((void *) fd, EV_RXCHAR)) {THIS_RTN_ERROR}

do  {
        if(ReadFile((void *) fd, szBuf, 1, &dwIncommingReadSize, NULL) != 0) {
            if(dwIncommingReadSize > 0) {
                for (k=0; k<dwIncommingReadSize; k++) {
                  *(line_buf+dwSize+k) = szBuf[k];
                }
                dwSize += dwIncommingReadSize;
            }
        }
        else {THIS_RTN_ERROR;}
    } while(dwIncommingReadSize > 0);
k = dwSize;
return(k);