locked
Datagridview and unbound checkbox column RRS feed

  • Question

  • Hi

    I' have a Datagridview(dgv) bound to a dataTable with 4 columns

    Then by code I add a checkboxcolumn to the dgv

    I can check different columns with the checkbox.

    But if I sort a column  the DGV all  rows checked before are not more checked.

    How to avoid this ?

    Wednesday, February 21, 2018 7:28 PM

Answers

  • Okay here is the fix for the tool-strip button. Note I updated my code sample to use a BindingSource which provides us to the current DataRow for accepting changes on the current row. I did this also in my MSDN code sample.

    Code

    Public Class Form1
        Protected ReadOnly bs As New BindingSource
        Private Sub Form1_Load(sender As Object, e As EventArgs) _
            Handles MyBase.Load
    
            Dim ops As New Operations
            bs.DataSource = ops.Read()
            DataGridView1.DataSource = bs
    
        End Sub
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) _
            Handles Button1.Click
    
            Dim checkedRows = CType(bs.DataSource, DataTable).
                    GetRowsChecked("Process")
    
            If checkedRows.Count > 0 Then
                checkedRows.ForEach(
                    Sub(row) Console.WriteLine(String.Join(",", row.ItemArray)))
            End If
        End Sub
    
        Private Sub ToolStripButton1_Click(sender As Object, e As EventArgs) _
            Handles ToolStripButton1.Click
    
            Dim dt As DataTable = CType(bs.DataSource, DataTable).Clone()
    
            Dim checkedRows = CType(bs.DataSource, DataTable).
                    GetRowsChecked("Process")
    
            If checkedRows.Count > 0 Then
                For Each row As DataRow In checkedRows
                    dt.ImportRow(row)
                Next
                Dim f As New Form2
                Try
                    f.DataGridView1.DataSource = dt
                    f.ShowDialog()
                Finally
                    f.Dispose()
                End Try
            End If
    
        End Sub
        Private Sub DataGridView1_CurrentCellDirtyStateChanged(sender As Object, e As EventArgs) _
            Handles DataGridView1.CurrentCellDirtyStateChanged
    
            CType(bs.Current, DataRowView).Row.AcceptChanges()
            DataGridView1.EndEdit()
    
        End Sub
    End Class
    


    Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.
    VB Forums - moderator
    profile for Karen Payne on Stack Exchange, a network of free, community-driven Q&A sites

    • Marked as answer by Claudio111 Saturday, February 24, 2018 7:47 PM
    Saturday, February 24, 2018 6:27 PM

All replies

  • Instead of altering the Grid View, maybe add a new column to DataTable:

       myDataTable.Columns.Add("Checked", GetType(Boolean))

    Sometimes this is enough; the new column in Grid View will appear automatically.


    Wednesday, February 21, 2018 7:48 PM
  • The data tanle cames from database. I do not want to alter it.
    Wednesday, February 21, 2018 8:17 PM
  • The additional field would not be bound to the database so it would not be saved in the database. There is not a field in the database for the additional field to go to, right?


    Sam Hobbs
    SimpleSamples.Info

    Wednesday, February 21, 2018 8:29 PM
  • If you look at the customers form in the following code sample you will see what Viorel_ means. You also need to set the default value to false else you will get a null exception raised when attempting to use the DataGridView Checkbox cell.

    Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.
    VB Forums - moderator
    profile for Karen Payne on Stack Exchange, a network of free, community-driven Q&A sites

    Wednesday, February 21, 2018 9:31 PM
  • Hi Karen,

    following your code samle now I am able to check rows in DGV .

    I still have a problem, when I check the first row and look at checked rows list  i get Nothing checked.

    IF I check one more row, I get in the list, the previous rows checked.

    It seems that I have to click on a different cell of checked row to get it in the list of checkd rows.

    Saturday, February 24, 2018 11:44 AM
  • Hi Karen,

    following your code samle now I am able to check rows in DGV .

    I still have a problem, when I check the first row and look at checked rows list  i get Nothing checked.

    IF I check one more row, I get in the list, the previous rows checked.

    It seems that I have to click on a different cell of checked row to get it in the list of checkd rows.

    Are you loading data from a database table? If so is it SQL-Server or MS-Access? I can put a code sample together dependent on answering my questions in VS2017. 

    Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.
    VB Forums - moderator
    profile for Karen Payne on Stack Exchange, a network of free, community-driven Q&A sites

    Saturday, February 24, 2018 12:37 PM
  • It is a sql data table. Always the same "Nazioni' table of other my last questions. I just added a checkbox columns in the UI in the way you suggest with your simple code
    Saturday, February 24, 2018 3:13 PM
  • The additional field would not be bound to the database so it would not be saved in the database. There is not a field in the database for the additional field to go to, right?


    Sam Hobbs
    SimpleSamples.Info

    Sam,

    It makes no sense for Claudio, Karen has given the impression that a Datatable is the same as a Recordset so that is what Claudio believes. I've given endless samples to him and they all fit very good in this question too. 

    But if I do that I see in 5 minutes a new reply with a bunch of code from Karen so it makes no sense. 


    Success
    Cor


    • Edited by Cor Ligthert Saturday, February 24, 2018 4:38 PM
    Saturday, February 24, 2018 3:41 PM
  • Here is what I just wrote and validated it works e.g. check one or more rows, get checked rows, sort, get changed rows, both match and not lost in the user interface.

    Get data

    Imports System.Data.SqlClient
    Public Class Operations
        Private ServerName As String = "KARENS-PC"
        Private Catalog As String = "NorthWindAzure"
        Private ConnectionString As String =
           $"Data Source={ServerName};Initial Catalog={Catalog};" &
           "Integrated Security=True"
    
        Public Function Read() As DataTable
            Dim dt As New DataTable
    
            Using cn As New SqlConnection With {.ConnectionString = ConnectionString}
                Using cmd As New SqlCommand With {.Connection = cn}
                    cmd.CommandText = "SELECT CustomerIdentifier, CompanyName,Country " &
                                      "FROM Customers"
    
                    cn.Open()
                    dt.Load(cmd.ExecuteReader())
    
                    dt.Columns.Add(New DataColumn() With
                        {
                            .ColumnName = "Process",
                            .DataType = GetType(Boolean),
                            .DefaultValue = False
                        })
    
                    dt.Columns("process").SetOrdinal(0)
                    dt.Columns("CustomerIdentifier").ColumnMapping = MappingType.Hidden
    
                End Using
            End Using
    
            Return dt
    
        End Function
    End Class
    

    Code module with language extension used in the next code block for the form

    Public Module LanguageExtensions
        <DebuggerStepThrough()>
        <Runtime.CompilerServices.Extension()>
        Public Function GetRowsChecked(
            pDataTable As DataTable,
            pColumnName As String) As List(Of DataRow)
    
            Return pDataTable.AsEnumerable.
                Where(Function(row) row.Field(Of Boolean)(pColumnName)).ToList
        End Function
    End Module
    

    Form code

    Public Class Form1
        Private Sub Form1_Load(sender As Object, e As EventArgs) _
            Handles MyBase.Load
    
            Dim ops As New Operations
            DataGridView1.DataSource = ops.Read()
    
        End Sub
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) _
            Handles Button1.Click
    
            Dim checkedRows = CType(DataGridView1.DataSource, DataTable).
                    GetRowsChecked("Process")
    
            If checkedRows.Count > 0 Then
                checkedRows.ForEach(
                    Sub(row) Console.WriteLine(String.Join(",", row.ItemArray)))
            End If
        End Sub
    End Class
    

    Before and after sort


    Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.
    VB Forums - moderator
    profile for Karen Payne on Stack Exchange, a network of free, community-driven Q&A sites

    Saturday, February 24, 2018 3:47 PM
  • Karen

    The problem is not the DataTable (from Database or hard coded) The work well

    I found the following problem

    I get the right list of checked rows if I use Button1 of your sample code

    If I use a Toolstripmenuitem to get the list (using the same code for Button1 click event, the list is not right. ( the last row checked is never showed unless I click on other cell even in different row)

    So the problem is using tollstripmenu item

    I tried on your code CheckedSimple_mocked

    Saturday, February 24, 2018 5:20 PM
  • Okay here is the fix for the tool-strip button. Note I updated my code sample to use a BindingSource which provides us to the current DataRow for accepting changes on the current row. I did this also in my MSDN code sample.

    Code

    Public Class Form1
        Protected ReadOnly bs As New BindingSource
        Private Sub Form1_Load(sender As Object, e As EventArgs) _
            Handles MyBase.Load
    
            Dim ops As New Operations
            bs.DataSource = ops.Read()
            DataGridView1.DataSource = bs
    
        End Sub
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) _
            Handles Button1.Click
    
            Dim checkedRows = CType(bs.DataSource, DataTable).
                    GetRowsChecked("Process")
    
            If checkedRows.Count > 0 Then
                checkedRows.ForEach(
                    Sub(row) Console.WriteLine(String.Join(",", row.ItemArray)))
            End If
        End Sub
    
        Private Sub ToolStripButton1_Click(sender As Object, e As EventArgs) _
            Handles ToolStripButton1.Click
    
            Dim dt As DataTable = CType(bs.DataSource, DataTable).Clone()
    
            Dim checkedRows = CType(bs.DataSource, DataTable).
                    GetRowsChecked("Process")
    
            If checkedRows.Count > 0 Then
                For Each row As DataRow In checkedRows
                    dt.ImportRow(row)
                Next
                Dim f As New Form2
                Try
                    f.DataGridView1.DataSource = dt
                    f.ShowDialog()
                Finally
                    f.Dispose()
                End Try
            End If
    
        End Sub
        Private Sub DataGridView1_CurrentCellDirtyStateChanged(sender As Object, e As EventArgs) _
            Handles DataGridView1.CurrentCellDirtyStateChanged
    
            CType(bs.Current, DataRowView).Row.AcceptChanges()
            DataGridView1.EndEdit()
    
        End Sub
    End Class
    


    Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.
    VB Forums - moderator
    profile for Karen Payne on Stack Exchange, a network of free, community-driven Q&A sites

    • Marked as answer by Claudio111 Saturday, February 24, 2018 7:47 PM
    Saturday, February 24, 2018 6:27 PM
  • Ok Karen

    the problem is solved just with the 

    Private Sub DataGridView1_CurrentCellDirtyStateChanged(sender As Object, e As EventArgs) _
            Handles DataGridView1.CurrentCellDirtyStateChanged
    
            CType(bs.Current, DataRowView).Row.AcceptChanges()
            DataGridView1.EndEdit()
    
        End Sub

    without changing the code for Button1 and Toolstripmenu Item clieck event.

    Can you tell me why you changed this code for ToolstripMenuItem click event, cloning the DataTable 

    In Any case thank you very much.    Everithing works now

    Claudio

    Saturday, February 24, 2018 7:08 PM
  • I've given endless samples to him and they all fit very good in this question too. 

    I have not spent the time to study the code in this thread very much but I believe you that you have offered useful and relevant code.


    Sam Hobbs
    SimpleSamples.Info

    Saturday, February 24, 2018 7:20 PM
  • The cloning was purely for demo purposes, not needed for your issue.

    Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.
    VB Forums - moderator
    profile for Karen Payne on Stack Exchange, a network of free, community-driven Q&A sites

    Saturday, February 24, 2018 7:31 PM
  • ok,  Thank you again Karen

    Saturday, February 24, 2018 7:46 PM