简体   繁体   English

将选定的行从 DataGridView 复制到另一个,包括图像列

[英]Copy selected rows from a DataGridView to another, including Image Column

I'm currently trying to copy selected rows from one DataGridView to another.我目前正在尝试将选定的行从一个 DataGridView 复制到另一个。
I'm trying to capture the value of the CheckBox, where if it's checked, then the entire row will be copied to another DataGridView.我试图捕获 CheckBox 的值,如果它被选中,那么整行将被复制到另一个 DataGridView。

For example, like add to cart then review cart.例如,添加到购物车然后查看购物车。 I've referred to the following post:我参考了以下帖子:
Copy selected datagridrow to new datagridview on different form 将选定的数据网格复制到不同表单上的新数据网格视图

However it doesn't seem to help.然而,它似乎没有帮助。
I've tried using a For loop like the one below, but I'm not entirely sure how to go about this.我试过使用像下面这样的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 : 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

What I'm doing here isn't working and I have no idea how to go about this.我在这里所做的不起作用,我不知道该怎么做。
Any help would be appreciated, thank you, kindly.任何帮助将不胜感激,谢谢,请。

Whenever I run this code, I get the error:每当我运行此代码时,都会收到错误消息:

System.NullReferenceException: Object reference not set to an instance of an object System.NullReferenceException:未将对象引用设置为对象的实例

I'm not sure how to fix it.我不知道如何解决它。

This is what the DataGridView looks like:这是 DataGridView 的样子:

什么DGV看起来像

This question is strictly related to the previous one:这个问题与上一个严格相关:
Display images in a DataGridView column using JSON objects as DataSource使用 JSON 对象作为数据源在 DataGridView 列中显示图像

You're using a sub-class ( Result ) of the RootObject to fill the first DataGridView.您正在使用RootObject的子类 ( Result ) 来填充第一个 DataGridView。

Modify the Result class as follows:修改Result类如下:

  • Add a new property, Selected As Boolean , decorated with a <JsonIgnore> attribute.添加一个新属性Selected As Boolean ,用<JsonIgnore>属性<JsonIgnore>
  • Add a new sub-class, called SelectionResult here, a selection of properties of the Result class that you think are needed in the second DataGridView to show the selected products.添加一个新的子类,在此处称为SelectionResult ,您认为在第二个 DataGridView 中需要选择Result类的属性来显示所选产品。
  • Add a copy method to the Result class which returns a sub-section of itself as a SelectionResult object.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
  • Add two List(Of Class) as Fields in the Form.在表单中添加两个List(Of Class)作为字段。 The main class, in the previous question, was called ProductsQuery , so I'm re-using the names already defined there:在上一个问题中,主类被称为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)()
  • In the method that fills the first DataGridView, initialize the CurrentProducts List:在填充第一个 DataGridView 的方法中,初始化CurrentProducts List:

     CurrentProducts = New List(Of ProductsQuery.Result)()
  • After the JSON has beed deserialized, fill the List with the JSON results:在 JSON 被反序列化后,用 JSON 结果填充 List:

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

In the event handler of the Button that adds the selected products to the second DataGridView, insert this code:在将所选产品添加到第二个 DataGridView 的 Button 的事件处理程序中,插入以下代码:

Edit :编辑
The SelectedProducts list preserves the items selected in the first DataGridView: only the items that are not already in the CurrentProducts list are added to the selection. SelectedProducts列表保留在第一个 DataGridView 中选择的项目:仅将不在CurrentProducts列表中的项目添加到选择中。

The btnRemoveSelection Button removes the selected items in the second DataGridView from the SelectedProducts list. btnRemoveSelection Button 从SelectedProducts列表中删除第二个 DataGridView 中的选定项。 The DataGridView Row selection is somewhat cumbersome, so might want to add a CheckBox Column to ease the selection of the items to remove. 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

This fills the List(Of SelectedProducs) with the selected elements of the first DataGridView and sets the DataSource of the second DataGridView to this List.这将使用第一个 DataGridView 的选定元素填充List(Of SelectedProducs)并将第二个 DataGridView 的 DataSource 设置为此列表。

Note that the first Column of the DataGridView is set to Visible = False , because that Column corresponds to the ID property of the element selected请注意,DataGridView 的第一 Column 设置为Visible = False ,因为该 Column 对应于所选元素的ID属性

The GetSelectionResult() of the Result class returns the properties values that have been defined in the SelectionResult class. Result类的GetSelectionResult()返回在SelectionResult类中定义的属性值。 You can of course re-define this class to contain whatever properties you see fit.您当然可以重新定义此类以包含您认为合适的任何属性。


This is the result of these modifications:这是这些修改的结果:

DataGridView JSON 结果

If you are databinding correctly, your underlying data will update when the checkbox is clicked.如果数据绑定正确,则单击复选框时,基础数据将更新。 Then you can just use some LINQ.然后你可以只使用一些 LINQ。 You should avoid iterating over your DataGridViewRows whenever possible (here it is possible) because they shouldn't hold the data, rather display it.您应该尽可能避免迭代 DataGridViewRows(这里是可能的),因为它们不应该保存数据,而是显示它。

This simple example works in a form with two DataGridViews and one Button with default names, in vb.net.这个简单的示例在 vb.net 中以具有两个 DataGridView 和一个具有默认名称的 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

在此处输入图片说明

You are currently using 2 separate DataTables.您当前正在使用 2 个单独的数据表。 Also you are attempting to add row each time you set a column value.此外,您每次设置列值时都试图添加行。 This might work for you.这可能对你有用。

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

Private Sub AppendColumnsToDGV2(dt As 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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM