Question Return the value of a Checkbox from a DataGridView

Fedaykin

Active member
Joined
Mar 20, 2013
Messages
30
Programming Experience
Beginner
I have a DataGridView that is populated by a DataSet. I'm attempting to return the value of a CheckBox in the DataGridView so I can color the row orange:

VB.NET:
        For Each band As DataGridViewBand In DataGridView1.Rows
            If DataGridView1.Rows(band.Index).Cells("HOLD").Value = CheckState.Checked Then
                band.DefaultCellStyle.BackColor = Color.DarkOrange
            End If
        Next

The code above throws:
A first chance exception of type 'System.InvalidCastException' occurred in Microsoft.VisualBasic.dll

I have attempted replacing the CheckedState.Checked with True, 1 etc. Any thoughts?
 
Your For Each loop doesn't make sense. If you want to access a row then why use DataGridViewBand? It's a row so use it as a row:
For Each row As DataGridViewRow In DataGridView1.Rows
    If row.Cells("HOLD").Value
As for the issue, the first question is whether the column can contain NULL values. If so then some of the cell values will be DBNull.Value, which can't be cast as Boolean or CheckState or anything else. That seems the most likely issue to me. If that is indeed the case then you need to first decide whether having NULL in that column makes sense and, if it doesn't, takes steps to make sure that it never does. In that case, the correct code would be:
If CBool(row.Cells("HOLD").Value) Then
    row.DefaultCellStyle.BackColor = Color.DarkOrange
otherwise use this:
Dim cellValue As Object = row.Cells("HOLD").Value

If cellValue IsNot DBNull.Value AndAlso CBool(cellValue) Then
    row.DefaultCellStyle.BackColor = Color.DarkOrange
 
Thank you for the education!

I have not used AndAlso or CBool before so these are brand new tools for me. I had originally tried using DataGridViewRow, but kept running into an error no doubt because of the Null values.

Here is the version I went with:

VB.NET:
        For Each row As DataGridViewRow In DataGridView1.Rows


            Dim cellValue As Object = row.Cells("HOLD").Value


            If cellValue IsNot DBNull.Value AndAlso CBool(cellValue) Then
                row.DefaultCellStyle.BackColor = Color.DarkOrange
            End If
        Next

I really appreciate the time you took.
 
By way of further explanation, the Value property of a DataGridViewCell is type Object because it has to be able to store all sorts of different objects. As such, you should cast the object as its actual type before using it, and in fact must do so if you have Option Strict On. The 'cellValue' variable is declared as Object because, at that stage, we don't know whether the cell contains a DBNull or a Boolean. The If statement first tests whether that object is DBNull.Value and, if it's not, it casts it as type Boolean using CBool and determines whether that Boolean value is True.

'AndAlso' is used because, unlike And, it short-circuits. That means that the second condition is only evaluated if it can make a difference to the overall result. In this case, if the cell value is NULL then the whole expression can never be True so there's no point even evaluating the second part, so AndAlso doesn't evaluate the second part. You should pretty much always use AndAlso in preference to And. Likewise, use OrElse rather than Or.
 
Thank you! That is a very easy to understand explanation. I've only been coding for about 7 months. I've written a pretty big application for my company that interfaces with our product handling SQL database and has quite a few stand alone modules for handling time clock, corrective actions, storing product history etc. I'm proud that it's up and running, but I have mainly just been 'doing it' rather than understanding every nuance of the code. I'm developing a new appreciation for variable types and code efficiency. I'm going back through and refining a lot of earlier code that I wrote so I can see that AndAlso, OrElse will be very useful toward that goal.
 
Back
Top