none
add checkbox on a datagridview RRS feed

  • Question

  • ive added my checkbox on my datagrid but when I run and click the checkbox it wont check here is my code

    Dim chk As New DataGridViewCheckBoxColumn()
            DataGridView1.Columns.Add(chk)
            chk.HeaderText = "Action"
            chk.Name = "chk"

    Friday, September 28, 2018 11:06 AM

Answers

  • That should work, here I construct the column and add a row, you can also comment out the add row and it still allows checking the column. Remember to have allow the DataGridView to add new rows else this will not work.

    Public Class Form1
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            DataGridView1.Columns.Add(New DataGridViewCheckBoxColumn With {.Name = "ProcessColumn", .HeaderText = "X"})
            DataGridView1.Rows.Add(New Object() {True})
        End Sub
    End Class

    Edit, thought the following code sample may be of interest I wrote on DataGridViewCheckBox

    https://code.msdn.microsoft.com/Bascis-to-advance-working-7b757af3?redir=0

    Since DataTable objects have been entered into this here is an example that uses mocked data to demostrate using a DataGridViewCheckBoxColumn. Note the use of DefaultValue for the CheckBox column.  Lastly, I used a BindingSource as with this you can a) subscribe to PositionChanged event where the Current property of the BindingSource is an Object which can be casted to a DataRowView then access the Row (DataRow) then any field on the current row in the DataGridView without the need to reference the DataGridView. You can do this also say from a Button click event etc.

    Public Class frmMainForm
        WithEvents bsRooms As New BindingSource
        Private Sub Form_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
            DataGridView1.AutoGenerateColumns = False
            bsRooms.DataSource = GetMockedData()
            DataGridView1.DataSource = bsRooms
        End Sub
        Private Function GetMockedData() As DataTable
            Dim dt As New DataTable()
            dt.Columns.Add("Identifier", GetType(Integer))
            dt.Columns.Add("Room", GetType(String))
            dt.Columns.Add("RoomType", GetType(String))
            dt.Columns.Add("Rate", GetType(Decimal))
    
            dt.Columns.Add(New DataColumn With
                {
                    .ColumnName = "Available",
                    .DataType = GetType(Boolean),
                    .DefaultValue = False
                })
    
            dt.Rows.Add(10, "201A", "Suite", 98.99)
            dt.Rows.Add(20, "101A", "Suite", 120.99)
            dt.Rows.Add(30, "201B", "Suite", 99.99)
    
            dt.AcceptChanges()
    
            Return dt
    
        End Function
        Private Sub cmdSelected_Click(sender As Object, e As EventArgs) Handles cmdSelected.Click
            Dim sb As New Text.StringBuilder
            CType(bsRooms.DataSource, DataTable).
                AsEnumerable.
                Where(Function(row) row.Field(Of Boolean)("Available")).
                ToList.
                ForEach(Sub(row) sb.AppendLine(row.Field(Of String)("Room")))
    
            If sb.Length > 0 Then
                MessageBox.Show($"Rooms selected{Environment.NewLine}{sb.ToString}")
            End If
        End Sub
    
        Private Sub cmdCurrent_Click(sender As Object, e As EventArgs) Handles cmdCurrent.Click
            MessageBox.Show(CType(bsRooms.Current, DataRowView).Row.Field(Of String)("Room"))
        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



    Friday, September 28, 2018 11:29 AM
    Moderator
  • I says 'Rows cannot be programmatically added to the DataGridView's rows collection when the control is data-bound.' I already allow the DataGridView to add new rows
    • Marked as answer by no[one] Friday, September 28, 2018 2:23 PM
    Friday, September 28, 2018 1:50 PM
  • I says 'Rows cannot be programmatically added to the DataGridView's rows collection when the control is data-bound.' I already allow the DataGridView to add new rows

    When there is a DataTable for the DataGridView DataSource (see my code sample using a BindingSource)

    You can add rows as follows

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        CType(bsRooms.DataSource, DataTable).
            Rows.Add(New Object() {Nothing, "XDF1", "The best", 123D, True})
    End Sub
    
    'OR
    
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        CType(bsRooms.DataSource, DataTable).Rows.Add(New Object() {Nothing})
    End Sub


    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 no[one] Friday, September 28, 2018 2:19 PM
    Friday, September 28, 2018 2:04 PM
    Moderator

All replies

  • That should work, here I construct the column and add a row, you can also comment out the add row and it still allows checking the column. Remember to have allow the DataGridView to add new rows else this will not work.

    Public Class Form1
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            DataGridView1.Columns.Add(New DataGridViewCheckBoxColumn With {.Name = "ProcessColumn", .HeaderText = "X"})
            DataGridView1.Rows.Add(New Object() {True})
        End Sub
    End Class

    Edit, thought the following code sample may be of interest I wrote on DataGridViewCheckBox

    https://code.msdn.microsoft.com/Bascis-to-advance-working-7b757af3?redir=0

    Since DataTable objects have been entered into this here is an example that uses mocked data to demostrate using a DataGridViewCheckBoxColumn. Note the use of DefaultValue for the CheckBox column.  Lastly, I used a BindingSource as with this you can a) subscribe to PositionChanged event where the Current property of the BindingSource is an Object which can be casted to a DataRowView then access the Row (DataRow) then any field on the current row in the DataGridView without the need to reference the DataGridView. You can do this also say from a Button click event etc.

    Public Class frmMainForm
        WithEvents bsRooms As New BindingSource
        Private Sub Form_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
            DataGridView1.AutoGenerateColumns = False
            bsRooms.DataSource = GetMockedData()
            DataGridView1.DataSource = bsRooms
        End Sub
        Private Function GetMockedData() As DataTable
            Dim dt As New DataTable()
            dt.Columns.Add("Identifier", GetType(Integer))
            dt.Columns.Add("Room", GetType(String))
            dt.Columns.Add("RoomType", GetType(String))
            dt.Columns.Add("Rate", GetType(Decimal))
    
            dt.Columns.Add(New DataColumn With
                {
                    .ColumnName = "Available",
                    .DataType = GetType(Boolean),
                    .DefaultValue = False
                })
    
            dt.Rows.Add(10, "201A", "Suite", 98.99)
            dt.Rows.Add(20, "101A", "Suite", 120.99)
            dt.Rows.Add(30, "201B", "Suite", 99.99)
    
            dt.AcceptChanges()
    
            Return dt
    
        End Function
        Private Sub cmdSelected_Click(sender As Object, e As EventArgs) Handles cmdSelected.Click
            Dim sb As New Text.StringBuilder
            CType(bsRooms.DataSource, DataTable).
                AsEnumerable.
                Where(Function(row) row.Field(Of Boolean)("Available")).
                ToList.
                ForEach(Sub(row) sb.AppendLine(row.Field(Of String)("Room")))
    
            If sb.Length > 0 Then
                MessageBox.Show($"Rooms selected{Environment.NewLine}{sb.ToString}")
            End If
        End Sub
    
        Private Sub cmdCurrent_Click(sender As Object, e As EventArgs) Handles cmdCurrent.Click
            MessageBox.Show(CType(bsRooms.Current, DataRowView).Row.Field(Of String)("Room"))
        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



    Friday, September 28, 2018 11:29 AM
    Moderator
  • I almost always add a column to the datatable either before or after Fill/Load. This has other advantages such as filtering.

            Dim dt As New DataTable

    With dt 'adapter.fill / .Load(DataReader) .Columns.Add("Select", GetType(System.Boolean)) .Columns("Select").DefaultValue = False End With DataGridView1.DataSource = dt

    And you will no doubt want immediate feedback on CellContentClick event. 

        Private Sub DataGridView1_CurrentCellDirtyStateChanged(sender As Object, e As EventArgs) Handles DataGridView1.CurrentCellDirtyStateChanged
            DataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit)
        End Sub


    Live as if you were going to die today, learn as if you were going to live forever -Mahatma Gandhi


    • Edited by Gtripodi Friday, September 28, 2018 1:15 PM
    Friday, September 28, 2018 1:15 PM
  • I says 'Rows cannot be programmatically added to the DataGridView's rows collection when the control is data-bound.' I already allow the DataGridView to add new rows
    • Marked as answer by no[one] Friday, September 28, 2018 2:23 PM
    Friday, September 28, 2018 1:50 PM
  • I says 'Rows cannot be programmatically added to the DataGridView's rows collection when the control is data-bound.' I already allow the DataGridView to add new rows

    When there is a DataTable for the DataGridView DataSource (see my code sample using a BindingSource)

    You can add rows as follows

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        CType(bsRooms.DataSource, DataTable).
            Rows.Add(New Object() {Nothing, "XDF1", "The best", 123D, True})
    End Sub
    
    'OR
    
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        CType(bsRooms.DataSource, DataTable).Rows.Add(New Object() {Nothing})
    End Sub


    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 no[one] Friday, September 28, 2018 2:19 PM
    Friday, September 28, 2018 2:04 PM
    Moderator
  • I says 'Rows cannot be programmatically added to the DataGridView's rows collection when the control is data-bound.' I already allow the DataGridView to add new rows

    When there is a DataTable for the DataGridView DataSource (see my code sample using a BindingSource)

    You can add rows as follows

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        CType(bsRooms.DataSource, DataTable).
            Rows.Add(New Object() {Nothing, "XDF1", "The best", 123D, True})
    End Sub
    
    'OR
    
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        CType(bsRooms.DataSource, DataTable).Rows.Add(New Object() {Nothing})
    End Sub


    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

    I cant help but to question everything, and in this case, why would you go through all that rigmarole instead of just adding a boolean column to the datatable? A drawback I can see adding the column to the dgv is you loose the ease of RowFiltering, obviously you can continue with DGV type filter, and say a for block on bindingsource where the bool col = true is very helpful.

    Sorry if I am a pain, but if I see someone mopping the floor with a toothbrush, i want to hand them a mop...


    Live as if you were going to die today, learn as if you were going to live forever -Mahatma Gandhi

    Friday, September 28, 2018 2:31 PM
  • @Gtripodi, 

    This in short shows you can (but does not mean you should) add a DataGridViewCheckBoxColumn and have it function. Personally, the only time I've done this is when setting the backing DataColumn. But with that said, my rule of thumb (and it's been over ten years since I last did a Desktop app) would be to query a database table into a DataTable, append a DataColumn where the type would be Boolean and set the default value to False else it would be Null/Nothing.

    Public Class Form1
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            DataGridView1.Columns.Add(New DataGridViewCheckBoxColumn With {.Name = "ProcessColumn", .HeaderText = "X"})
            DataGridView1.Rows.Add(New Object() {True})
        End Sub
    End Class

    Then there is the case for doing this in TSQL e.g.

    DECLARE @ContactTypeIdentifier INT = 7; 
    SELECT  IIF(IIF(Customers.ContactTypeIdentifier = @ContactTypeIdentifier,  
                CONVERT(BIT, 1),  
                CONVERT(BIT, 0)) = 1,  
                'true', 'false') AS Process , 
            Customers.CustomerIdentifier , 
            Customers.CompanyName , 
            Customers.ContactName , 
            ContactType.ContactTitle 
    FROM    Customers 
            INNER JOIN ContactType ON Customers.ContactTypeIdentifier =  
            ContactType.ContactTypeIdentifier 
    WHERE   dbo.Customers.ContactTypeIdentifier IN ( 1, @ContactTypeIdentifier ) 
    ORDER BY ContactTitle; 

    The code for this is done in C# which is why I'm not posting it here but go here for the source.

    Concerning filtering directly in a DataGridView, never saw any advantages, always filtered on the DataSource.

    In regards to asking question and "Sorry if am a pain", I see no problem and wish that others would do that too

    What I don't care for is a novice developer not willing to take the time (and that is not the case here) to do research on classes and what not. So keep on asking and questioning :-)


    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

    Friday, September 28, 2018 3:00 PM
    Moderator
  • "Concerning filtering directly in a DataGridView, never saw any advantages, always filtered on the DataSource."

    I think you misread, or I wasnt clear enough. This is why I want the boolean in the datatable so that I can apply a RowFilter, and/or iterate the datasource(bindingsource) and do something when value is true

    Also, if you add the column to the DataTable and set its default value to false prior to the .Fill or .Load the value will be False in all rows.

    I appreciate all the time you spent/spend with me and others. Youre a wonderful instructor


    Live as if you were going to die today, learn as if you were going to live forever -Mahatma Gandhi


    • Edited by Gtripodi Friday, September 28, 2018 4:16 PM
    Friday, September 28, 2018 4:15 PM