Hi,
What I'm trying to do is quite simple.....
1. I've created a empty DataGridView
2. I add a DataGridViewCheckBoxColumn using the following code-
colToBeAdded = New DataGridViewCheckBoxColumn
colToBeAdded.FalseValue = 2
colToBeAdded.TrueValue = 1
colToBeAdded.ThreeState = False
colToBeAdded.valuetype = GetType(Integer)
colToBeAdded.HeaderText = headerText
colToBeAdded.Name = colName
colToBeAdded.DataPropertyName = colName
dgItemSelect.Columns.Add(colToBeAdded)
3. I then bind my datatable to the datagrid view:-
dgItemSelect.DataSource = dt
The datatable contains a column of type integer which only has values of 1 and 2. 1 is supposed to be true and 2 is supposed to be false.
When I look at the dgv it seems to be ignoring my .FalseValue and .TrueValue properties I've set in the code above. The checkbox cells are all checked - they seems to be behaving in the default manner i.e. if the datatable column contains a 1 or a 2 the application reads this as 'true' and the checkboxes appear as checked.
Can anyone shed any light on this particular conundrum . Am I way of the mark It's probably something quite simple but I can't seem to get this working.
Many thanks
Stuart

Change the checked and unchecked value of a DataGridViewCheckBoxColumn
Robin Lundgren
Ok, I don't understand all this but working off a key statement in the help, namely "In the case of check box cells, however, you will typically want to handle the change immediately", I was able to figure out a way for this to work - whether it it is the right way or a good way is another story.
Basically, I added handlers for the CurrentCellDirtyStateChanged and the CellFormatting events and this seems to fix things (at least in ThreeState = False mode).
Here's the relevant code:
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Loaddgv1.AllowUserToAddRows =
Truedgv1.AllowUserToDeleteRows =
Truedgv1.AllowUserToOrderColumns =
Truedgv1.AllowUserToResizeColumns =
Truedgv1.AllowUserToResizeRows =
True dgv1.RowHeadersVisible = Truedgv1.ColumnHeadersVisible =
True dgv1.ColumnHeadersBorderStyle = DataGridViewHeaderBorderStyle.Singledgv1.AutoGenerateColumns =
False Dim column As DataGridViewColumn = New DataGridViewTextBoxColumn()column.DataPropertyName =
"Col1"column.Name =
"Col 1 Hdr"column.ValueType =
GetType(String)dgv1.Columns.Add(column)
column =
New DataGridViewTextBoxColumn()column.DataPropertyName =
"Col2"column.Name =
"Col 2 Hdr"column.ValueType =
GetType(System.DateTime)dgv1.Columns.Add(column)
Dim chkcol As DataGridViewCheckBoxColumn = New DataGridViewCheckBoxColumn()chkcol.CellTemplate =
New DataGridViewCheckBoxCell() chkcol.Name = "Col 3 Hdr"chkcol.ValueType =
GetType(System.Int32)chkcol.ThreeState =
Falsechkcol.TrueValue =
CInt(9)chkcol.FalseValue =
CInt(3) dgv1.Columns.Add(chkcol)dgv1.ColumnCount = 3
Dim columnStyleR As New DataGridViewCellStyle()columnStyleR.Alignment = DataGridViewContentAlignment.TopRight
columnStyleR.Format =
"D" Dim columnStyleL As New DataGridViewCellStyle()columnStyleL.Alignment = DataGridViewContentAlignment.TopLeft
columnStyleL.Format =
""dgv1.Columns(0).DefaultCellStyle = columnStyleL
dgv1.Columns(1).DefaultCellStyle = columnStyleR
Dim row1 As Object() = {"Bye", CDate("2/17/06"), 3}dgv1.Rows.Add(row1)
Dim row2 As Object() = {"Hello", CDate("02/15/06"), 9}dgv1.Rows.Add(row2)
End Sub
Private Sub dgv1_CellFormatting(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellFormattingEventArgs) Handles dgv1.CellFormatting If e.ColumnIndex = 2 ThenDebug.Print(
"dgv1_CellFormatting Row=" & e.RowIndex & ", Col=" & e.ColumnIndex & ", Value=" & e.Value & ", DesiredType=" & e.DesiredType.ToString & ", CellStyle=" & e.CellStyle.ToString) If dgv1.Rows(e.RowIndex).Cells(e.ColumnIndex).Value = 9 Then e.Value = True Else e.Value = Falsee.FormattingApplied =
True End If End Sub
Private Sub dgv1_CurrentCellDirtyStateChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles dgv1.CurrentCellDirtyStateChanged If dgv1.CurrentCell.ColumnIndex = 2 Then If dgv1.IsCurrentCellDirty Thendgv1.CommitEdit(DataGridViewDataErrorContexts.Commit)
End If End If End SubWhy I have to format the cell settung the FormattedValue to True or False based on the Vlaue is beyond me, you would think since the cell knows the TrueValue and the FalseValue, that it would od this automatically, but it does not appear to. I have an itch to report this as a bug. What do you think
neuroma
Uh, yeah, I have the same problem here. I have a checkbox column whose FalseValue is 3 and whose TrueValue is 9 and the grid is not bound. Even though the .Value is set correctly, the .FormattedValue is always True and the checkbox is always checked after editing and leaving the cell. It is almost as if the FormattedValue is not being set correctly based on the Value when leaving the cell.
I think I will check the bug forum and let you know if I find anything .
jklegseth
Cheers for keeping this one alive - I'm determined to get to the bottom of this particular DataGridViewCheckBoxColumn conundrum!
Thanks (again!) for replying vkh75. Your solution is perfectly workable but I'm looking for a neater fix. I'd rather not create a 'fake' column of checkboxes as we should be able to set the 'checked' value of a checkboxcolumn. Ta!
Any joy on the Bug Forum Matty4242 I had look and found nothing. You should be able to set the checkbox FalseValue to 3 and TrueValue to 9 - the documentation certainly suggests you can - but it the solution remains elusive.
Any other .netters, datagrid guru's or even the Microsoft Team have any views on this
Go on, go on, go on.......
Cheers
Stuart
AlsoDave
The DataGridViewCheckBoxCell treats non-zero integers as TRUE value. One workaround is to inherit from the DataGridViewCheckBoxColumn/Cell like and override GetFormattedValue method, just like Stuart suggested.
Here is a similar fix to the fix Stuart posted, it is a bit more general - the values 9 and 13 are not hard coded, so this check box cell can be used w/ True/False values other than 9/13.
Here is the code for GetFormattedValue ( apologies in advance, CSharp only ). This implementation only deals w/ DataGridViewCheckBoxes where ThreeState is set to FALSE, but the solution can be extended to DataGridViewCheckBoxes where ThreeState is set to TRUE.
protected
override object GetFormattedValue(object value, int rowIndex, ref DataGridViewCellStyle cellStyle, TypeConverter valueTypeConverter, TypeConverter formattedValueTypeConverter, DataGridViewDataErrorContexts context){
// TODO: add similar logic for ThreeState = true. if (value != null && value.Equals(this.TrueValue)){
value =
true;}
else if (value != null && value.Equals(this.FalseValue)){
value =
false;}
return base.GetFormattedValue(value, rowIndex, ref cellStyle, valueTypeConverter, formattedValueTypeConverter, context);}
Hope this helps,
Daniel.
JamieWP
Hey Matty
Got a solution of sorts here. Hope it if will suit your problemo (sounds like it would be close) but here's what I've done (bear with me this is new territory for me). It's a shame it isn't slightly more straightforward but here it is......
Public Class SapphireCheckBoxColumn
Inherits DataGridViewColumn
Public Sub New()
MyBase.New(New SapphireCheckBoxCell())
End Sub
End Class
Public Class SapphireCheckBoxCell
Inherits DataGridViewCheckBoxCell
Public Sub New()
MyBase.Style.SelectionBackColor = Drawing.Color.White
MyBase.Style.Alignment = DataGridViewContentAlignment.MiddleCenter
MyBase.TrueValue = 9
MyBase.FalseValue = 13
End Sub
Protected Overrides Function GetFormattedValue(ByVal value As Object, ByVal rowIndex As Integer, ByRef cellStyle As System.Windows.Forms.DataGridViewCellStyle, ByVal valueTypeConverter As System.ComponentModel.TypeConverter, ByVal formattedValueTypeConverter As System.ComponentModel.TypeConverter, ByVal context As System.Windows.Forms.DataGridViewDataErrorContexts) As Object If CInt(value) = 13 Thenvalue = 0
ElseIf CInt(value) = 9 Thenvalue = 1
End If Return MyBase.GetFormattedValue(value, rowIndex, cellStyle, valueTypeConverter, formattedValueTypeConverter, context) End FunctionEnd
ClassSo we create our own custom column and cell types and set the TrueValue and FalseValue to your own values. Finally we override the GetFormattedValue function and change it's return values.
Just change your code:
Dim chkcol As DataGridViewCheckBoxColumn = New DataGridViewCheckBoxColumn()
to
Dim chkcol As SapphireCheckBoxColumn= New SapphireCheckBoxColumn()
Any improvements would be most welcome!
Hope this helps.
Cheers
Stuart
sethgold
Stuart
Bulldog.NET
No, nothing in bug listings for me either. I am thinking this has something to do with committing the change to the cell, or with the ThreeState property so I have re-read Mark Rideout's FAQ on the DGV but still have not figured out how to get it set.
Each cell has a Value and a Formatted Value and a ValueType and a FormattedValueType With ThreeState = False, the FormattedValueType is Boolean and can't be changed and the FormattedValue always seems to be True or False, which makes sense. The odd thing is when I look at the Value and ValueType, they actually agree with what I expect: False = 3 and True = 9. The problem is that the display of the checkbox does not agree with the Value or the FormattedValue. For example, I can have a Value = 3 (False) and a FormattedValue = False, but the checkbox is checked (My eyes are spinning in their sockets right now).
I will keep trying.
JeffOzvold
Ok, I'll back off a little, it looks like we do NOT need the CurrentCellDirtyStateChanged event, just the CellFormatting event.
It looks like ThreeState = True works also, but of course, the CellFormatting event must handle this appropriately and the IndeterminateValue must be set as well.
Hope this stuff helps.
johnfrost
Thanks for replying vkh75. Naturally I consulted MSDN before posting on this forum.
The documentation states the following regarding .TrueValue:
"Gets or sets the underlying value corresponding to a cell value of true. "
"Setting the TrueValue property of the owning column also sets the TrueValue property of every cell in the column and refreshes the column display. To override the specified value for individual cells, set the cell values after you set the column value."
Maybe I'm still misunderstanding what's being said here but it seems to suggest that you can specify the "true" value of a checkbox.
Your proposed answer is workable but I'd prefer a more elegant solution. Changing the values of the datatable before I bind to the the datagridview and then changing them back again before I save the changes to the database is a pretty clumbsy way of doing things (unfortuantley I can't alter the underlying data in the database as other systems rely on it's structure).
Any further thoughts
Cheers again for the reply!
Stuart
TobyKraft
meilon
Here is another thought...
Create two DataGridViewColumns. The first column is a DataGridViewTextBoxColumn that is bound and contains either 1 or 2 values. Let's call it "tCol". Make it invisible as users don't need to see it. The second column is an unbound DataGridViewCheckBoxColumn (let's name it "bCol"). It will be checked or unchecked depending on the values of tCol. Then you'll have to use the CellFormatting and CellParsing events of your DataGridView.
CellFormatting event handler may look like:
Dim dgv As DataGridView = CType(sender, DataGridView)
If dgv.Columns(e.ColumnIndex).Name = "bCol" Then
If dgv("tCol", e.RowIndex).Value = 1 Then
e.Value = True
Else
e.Value = False
End If
End If
And CellParsing event handler may contain the code:
Dim dgv As DataGridView = CType(sender, DataGridView)
If dgv.Columns(e.ColumnIndex).Name = "bCol" Then
If e.Value = True Then
dgv("tCol", e.RowIndex).Value = 1
Else
dgv("tCol", e.RowIndex).Value = 2
End If
End If
Hope it will help.
okaban
Glen Plantz
I wouldn't advise using this column unless you bind it to a boolean property in your datasource. Otherwise, it behaves like a piece of ***.
One more warning: If you try to initialize the boolean property's cell (say setting all rows to false so they don't display as checked) in the DataBindingComplete event, you'll cause the grid to go haywire and enter into an infinite loop constantly re-binding itself.
Stuart (not the same one above)