I'm writing an datagriview column to handle the user entering null values(in this case if a leave date is not set for a user it's stored as null and displayed as an N/A)
I've almost got it working using a nullable datetimepicker but the grid doesn't pick up on the change to a null value, it just switches back to the old time value. When the row is initialised it starts with a null value which displays fine.
This is then databound back to a model class
The Calendar Cell
public class CtlDataGridViewNullableCalendarCell : DataGridViewTextBoxCell
{
public CtlDataGridViewNullableCalendarCell()
: base()
{
this.Style.Format = "d";
}
public override void InitializeEditingControl(int rowIndex, object
initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
{
// Set the value of the editing control to the current cell value.
base.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle);
CtlCalendarNullableEditingControl ctl = DataGridView.EditingControl as CtlCalendarNullableEditingControl;
ctl.Value = (DateTime?)this.Value;
// a hacky way of getting the DateTimePicker to reset its focus, rather than remembering which date part was previously focussed
DateTimePickerFormat format = ctl.Format;
ctl.Format = DateTimePickerFormat.Custom;
ctl.Format = format;
}
public override object ParseFormattedValue(object formattedValue, DataGridViewCellStyle cellStyle, TypeConverter formattedValueTypeConverter, TypeConverter valueTypeConverter)
{
if (formattedValue == null)
return null;
else
return (formattedValue as DateTime?).Value.Date;
}
public override Type EditType
{
get
{
// Return the type of the editing control that CalendarCell uses.
return typeof(CtlCalendarNullableEditingControl);
}
}
public override Type ValueType
{
get
{
// Return the type of the value that CalendarCell contains.
return typeof(DateTime?);
}
}
public override object DefaultNewRowValue
{
get
{
// Use the current date as the default value.
return null;
}
}
#endregion
}
The Override for the editing control
class CtlCalendarNullableEditingControl : CtlNullableDateTimePicker, IDataGridViewEditingControl
{
DataGridView _dataGridView;
private bool _valueChanged = false;
int _rowIndex;
public object EditingControlFormattedValue
{
get
{
return this.Value;
}
set
{
if (value is string)
if ((string)value == string.Empty)
value = null;
else
value = DateTime.Parse((string)value);
}
}
public object GetEditingControlFormattedValue(
DataGridViewDataErrorContexts context)
{
return EditingControlFormattedValue as DateTime?;
}
public void ApplyCellStyleToEditingControl(
DataGridViewCellStyle dataGridViewCellStyle)
{
this.Font = dataGridViewCellStyle.Font;
this.CalendarForeColor = dataGridViewCellStyle.ForeColor;
this.CalendarMonthBackground = dataGridViewCellStyle.BackColor;
}
public int EditingControlRowIndex
{
get
{
return _rowIndex;
}
set
{
_rowIndex = value;
}
}
public bool EditingControlWantsInputKey(
Keys key, bool dataGridViewWantsInputKey)
{
// Let the DateTimePicker handle the keys listed.
switch (key & Keys.KeyCode)
{
case Keys.Left:
case Keys.Up:
case Keys.Down:
case Keys.Right:
case Keys.Home:
case Keys.End:
case Keys.PageDown:
case Keys.PageUp:
case Keys.Delete:
case Keys.Back:
return true;
default:
return false;
}
}
public DataGridView EditingControlDataGridView
{
get
{
return _dataGridView;
}
set
{
_dataGridView = value;
}
}
public bool EditingControlValueChanged
{
get
{
return _valueChanged;
}
set
{
_valueChanged = value;
}
}
#region -- DateTimePicker overrides --
/// <summary>
/// Handle the OnValueChanged event from the <see cref="DateTimePicker"/> and ensure the change propagates to the grid.
/// </summary>
/// <param name="eventargs"></param>
protected override void OnValueChanged(EventArgs eventargs)
{
// Notify the DataGridView that the contents of the cell have changed.
_valueChanged = true;
this.EditingControlDataGridView.NotifyCurrentCellDirty(true);
base.OnValueChanged(eventargs);
}
The Editing Control works perfectly on it's own so I'm sure the problem resides in the actual cell class but I'm not familiar with winforms enough to spot the problem.
And advice or even just pointers would be gratefully received.