I am modifying some code that has a custom calendar control using a DateTimePicker
for a DataGridView
. I have set ShowCheckBox = true
and I am trying to force it to change the value of the date to null when the user clicks on the checkbox (by changing the CustomFormat
of the Date), which works. My issue is that it takes too many clicks on the checkbox to change the DateFormat. My basic CalendarColumn comes from http://msdn.microsoft.com/en-us/library/7tas5c80.aspx, but that didn't include a checkbox and didn't allow null values.
My OnValueChanged()
code is:
protected override void OnValueChanged(EventArgs eventargs)
{
// Notify the DataGridView that the contents of the cell
// have changed.
base.OnValueChanged(eventargs);
if (this.Checked)
{
this.Checked = true;
this.Format = DateTimePickerFormat.Short;
} else if (!this.Checked)
{
this.Format = DateTimePickerFormat.Custom;
this.CustomFormat = " ";
}
}
The first click on the checkbox (when it's value is checked) greys out the date, but does not fire the OnValueChanged()
method, the second click sets it back to "checked", and fires the event, and the 3rd click sets the CustomFormat
to " " and therefore displays a null date as it should.
I've done some research, and I think that my issue is something to do with gaining focus of the cell on the first click, but if I put my check in the onGotFocus()
, a single click will show/hide the date format as it should, but then when I click onto another cell after unchecking the checkbox, it remains with the CustomFormat
set as " " rather than DateTimePickerFormat.Short
.
Other answers on a similar subject refer to http://www.mofeel.net/70-microsoft-public-dotnet-framework-windowsforms/8806.aspx, but I'm confused as to how I would incorporate this into my code. I haven't posted the whole class, but can do if anybody thinks that will help?
A collegue fixed this for me. I will try to explain as best I can:
My OnValueChanged()
method ended up looking like:
protected override void OnValueChanged(EventArgs eventargs)
{
valueChanged = true;
// Notify the DataGridView that the contents of the cell
// have changed.
this.EditingControlDataGridView.NotifyCurrentCellDirty(true);
base.OnValueChanged(eventargs);
isChecked();
}
public bool isChecked()
{
bool isChecked = false;
if (this.Checked)
{
this.Checked = true;
this.Format = DateTimePickerFormat.Short;
isChecked = true;
}
else if (!this.Checked)
{
this.Format = DateTimePickerFormat.Custom;
this.CustomFormat = " ";
isChecked = false;
}
return isChecked;
}
He also added these methods:
protected override void OnClick(EventArgs e)
{
isChecked();
base.OnClick(e);
}
public object EditingControlFormattedValue
{
get
{
if (!this.Checked)
{
return String.Empty;
}
else
{
if (this.Format == DateTimePickerFormat.Custom)
{
return this.Value.ToString();
}
else
{
return this.Value.ToShortDateString();
}
}
}
set
{
string newValue = value as string;
if (!String.IsNullOrEmpty(newValue))
{
this.Value = DateTime.Parse(newValue);
}
}
}
The InitializaEditingControl
was also edited to:
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);
ctl = DataGridView.EditingControl as CalendarEditingControl;
// ctl.Invalidated += new InvalidateEventHandler(ctl_Invalidated);
ctl.ValueChangedSpecial += new EventHandler(ctl_ValueChangedSpecial);
if (rowIndex >= 0)
{
try
{
if (String.IsNullOrEmpty(this.Value.ToString()))
{
ctl.Checked = false;
ctl.Format = DateTimePickerFormat.Custom;
ctl.CustomFormat = " ";
}
else
{
ctl.Checked = true;
ctl.Value = (DateTime)this.Value;
ctl.Format = DateTimePickerFormat.Short;
}
}
catch (ArgumentOutOfRangeException aex)
{
//MessageBox.Show("ERROR. " + aex.Message);
ctl.Value = (DateTime)this.DefaultNewRowValue;
}
}
}
And then it worked.
This answer is almost certainly unsatisfactory, but unanswered questions help nobody, so hopefully something here might help someone else.