0

I've got a project with a DataGridView showing data from a flat file database. There are 7 buttons that load an SQL querys result to the DGV, as well as adding a checkbox to select rows.

When a user selects a checkbox, that particular DataGridViewRow (DGVR) gets added to a temporary List(Of DGVR) for later use.

Then there's a final button that shows a second form, doing a comparison of the two entries selected, passing the temporary list to the second form.

Users will be able to select 1 from 2 different selections (hence the separate lists).

The problem is, if you click button 1, and choose a row, when you click a second button, the line that resets the datasource to the new query results apparently turns all existing DGVRs into null pointers.

IE: the references to the DGVR are lost.

If you pick one from the first button, and then one from the second button, then try and pass the two selected items, the first one will be null, but the second won't.

Code:

    Dim con As New OleDb.OleDbConnection
    Dim dbProvider As String
    Dim dbSource As String

    currentWeapon = "Sniper"

    Dim ds As New DataSet
    Dim da As New OleDb.OleDbDataAdapter
    Dim sql As String

    dbProvider = "PROVIDER=Microsoft.ACE.OLEDB.12.0;"
    dbSource = "Data Source = Resources/Battlefield 4 Weapons.accdb"
    con.ConnectionString = dbProvider & dbSource

    con.Open()

    sql = "SELECT * FROM [Battlefield 4 Weapons]"
    da = New OleDb.OleDbDataAdapter(sql, con)
    da.Fill(ds, "Battlefield 4 Weapons.accdb")

    con.Close()

    Dim dt As DataTable = ds.Tables(0)
    Dim dr As DataRow() = dt.Select("[Weapon type] = 'Sniper'", "Weapon Name")
    Dim miniDT As New DataTable

    miniDT = dr.CopyToDataTable()
    DataGridView1.DataSource = miniDT
    DataGridView1.Sort(DataGridView1.Columns("Weapon Name"), System.ComponentModel.ListSortDirection.Ascending)

    DataGridView1.MultiSelect = True

The line that nullifies the entries when a new button is pressed is the line:

        DataGridView1.DataSource = miniDT

Then, when the checkbox gets clicked, this code runs (with a case for each weapon type). AsList is the list designed to hold the rows temporarily before passing them over:

    DataGridView1.EndEdit()
    Select Case currentWeapon
        Case "Assault"

            Assaultlabel.Visible = True
            AsList.RemoveRange(0, AsList.Count)
            For i = 0 To DataGridView1.Rows.Count - 1
                If DataGridView1.Rows(i).Cells(14).Value = True Then
                    If Not AsList.Contains(DataGridView1.Rows(i)) Then
                        AsList.Add(DataGridView1.Rows(i))
                    End If
                End If
            Next

I've tried cloning the row, to create a copy that is separate, but that doesn't work. How can I separate it from the data source so that I can load a new set of data, but SAVE the selected rows?

Phil
  • 167
  • 6
  • It's not that the references to the rows are lost. It's that the rows they referred to no longer exist. If you're going to remove all the rows and then re-add them, which is what happened when you rebind, then you need to put the data into a collection for later use, not the rows containing the data. – jmcilhinney Aug 31 '14 at 07:56

1 Answers1

1

The DataGridView will remove all rows whenever the DataSource is changed. You always need to reference the underlying data. I think it's time to understand how a DataTable is bound to the grid.

When you set a new data source the grid will see if the type of the new object implements the IListSource interface. A DataTable implements this interface. It returns the DefaultView and it's actually this instance that the grid use as its source. The grid create new rows and each row are bound to a DataRowView (which in turn is bound to a DataRow).

DataGridView > DataView > DataTable

DataGridViewRow > DataRowView > DataRow

You can obtain a reference to a DataRowView through the DataBoundItem property of the DataGridViewRow:

Dim gridRow As DataGridViewRow = Me.DataGridView1.Rows(0)
Dim viewRow As DataRowView = DirectCast(gridRow.DataBoundItem, DataRowView)
Dim tableRow As DataRow = viewRow.Row

Instead of copying a data table, just create a new data view:

Dim view1 As New DataView(mytable)
Dim view2 As New DataView(mytable)

You can sort and filter a data view.

view1.Sort = "Name ASC"
view1.RowFilter = "Name = 'Smith' And Age >= 18"

Now you can use this DataView as the data source instead the default view.

Me.DataGridView1.DataSource = view1
Community
  • 1
  • 1
Bjørn-Roger Kringsjå
  • 9,849
  • 6
  • 36
  • 64
  • That makes sense in terms of updating the DataGridView1 object, but say I want to take the contents of the rows and send it somewhere else, how can I do that? Because I don't see how this solves my problem of extracting that data as a row and sending it to another form, because if I change the datasource to view1, view2, etc, I still would have copied the information out of view 1, so when I go to view2 I lose it. Unless you're suggesting I use the views sort / filters to act how I currently have queries? That way the datagridview row is referencing the full flat file behind the scenes? – Phil Aug 31 '14 at 09:56
  • Also, is "mytable" in your code example "dt" in my code above? – Phil Aug 31 '14 at 09:59
  • @Phil Not sure what you mean by *"send it somewhere else*". Yes, `mytable` is your `dt`. You can have mulitple `DataView`s, all referencing the same `DataTable`, on mulitple forms. Sorting and filtering will not affect the `DataTable`. But inserting, editing and deleting will be pushed to the `DataTable` and changes will be reflected on each `DataView`. I'm sorry but I cannot quite grasp the logic of your data flow. Can you provide a screenshot of your application? – Bjørn-Roger Kringsjå Aug 31 '14 at 10:46
  • My problem was a lack of understanding of how Databindings/sources work, as this area is new to me. I'm pretty sure I'm sorted now, as the views mean I can deal with the original rows, which will only get loaded once. If you want a screenshot for your own piece of mind I can give you one, but I'm sorted at my end. Cheers – Phil Aug 31 '14 at 21:45