A while back, I managed to fix a couple bugs with the sample DataGridView CalendarColumn control that made it much more usable. Today, I came across one more issue. It's pretty well known that the DateTimePicker, despite having support for a checkbox that lets you turn a date on or off, does not directly support "null" as a valid value. There are a bunch of ways to get around this, but what I came across was a need to support this inside of a DataGridView.
I started with the task of making the CalendarColumn configurable in such a way as to be able to turn the checkbox on or off at will (well, at least, at the moment of construction). That part's easy; I added a new constructor to CalendarColumn to take an "isNullable" flag:
Then, I added a class-level variable to my CalendarCell class, and initialized it in the constructor:
The next modification comes in InitializeEditingControl. Immediately after getting the reference to CalendarEditingControl ctl is set:
(Note that I added a little checking around the value setting area, because I'm paranoid like that.)
Here's what I found out you don't change. The ValueType property always returns typeof(DateTime). If you change this to typeof(DateTime?), what ends up happening is, if you bind to a DataTable, it attempts to insert an actual null into the table. Because (for reasons I have yet to believe necessary) null and DBNull are two completely separate and incompatible things, this fails. Apparently, by leaving the value type as non-nullable, a null value will get translated appropriately in the binding.
We're not quite done yet. In the CalendarEditingControl class, the EditingControlFormattedValue property needs to be updated:
And presto, a checkable, nullable DateTimePicker column that works in a DataGridView bound to a DataTable.