There are so many Nullable DateTimePickers out there that this post may not even be found among all the others, but I wanted to try. First, I want to thank all the authors of the code I used as a starting point. Second, I hope this code helps someone as much as they helped me.
I have built a Nullable DateTimePicker and NullableCalenda rColumn/Cell/EditingControl that is nearly 100% complete, as far as I can tell. There is only one remaining issue and it has me stalled.
When the user clicks into the cell containing the Nullable control (pleaced in a DataGridView), the first time, and only the first time, instead of the date already there, today's date appears. As an example, say that the cell contained 1/1/08, the DataGridView has just been created, and the user clicks (twice) in the cell to enable the EditingControl. Instead of 1/1/08, the date that appears is 7/20/08. Again, this happens only the very first time the control is used. After that it works as it should, initializing the control to the date in the cell.
Any thoughts?
Todd
P.S. Anyone that wants to expand on this or make disparaging comments about my code, feel free ... I can use all the help I can get!
*************** *************** *************** *************** **
NullableDateTim ePicker.cs
*************** *************** *************** *************** **
Expand|Select|Wrap|Line Numbers
- using System;
- using System.Collections;
- using System.ComponentModel;
- using System.Drawing;
- using System.Data;
- using System.Windows.Forms;
- namespace Custom
- {
- public class NullableDateTimePicker : System.Windows.Forms.DateTimePicker
- {
- private Boolean isNull = false;
- private DateTimePickerFormat baseFormat = DateTimePickerFormat.Short;
- private Boolean ignoreBindOnFormat = false;
- public NullableDateTimePicker()
- {
- this.Format = baseFormat;
- if (baseFormat == DateTimePickerFormat.Custom) this.CustomFormat = " ";
- }
- public Boolean IsNull
- {
- get { return isNull; }
- set
- {
- isNull = value;
- this.Checked = value;
- }
- }
- //TODO: Add BaseCustomFormat
- public DateTimePickerFormat BaseFormat
- {
- get { return baseFormat; }
- set { baseFormat = value; }
- }
- public object BindMe
- {
- get
- {
- if (IsNull) return System.DBNull.Value;
- else return base.Value;
- }
- set
- {
- String s = this.Name;
- if (ignoreBindOnFormat) return;
- if (System.Convert.IsDBNull(value))
- {
- // for some reason setting base.format in this.format calls set BindMe.
- // we need to ignore the following call
- ignoreBindOnFormat = true;
- this.Format = DateTimePickerFormat.Custom;
- this.CustomFormat = " ";
- IsNull = true;
- ignoreBindOnFormat = false;
- }
- else
- {
- this.Format = baseFormat;
- if (baseFormat == DateTimePickerFormat.Custom) this.CustomFormat = " ";
- IsNull = false;
- base.Value = (DateTime)value;
- }
- }
- }
- protected override void OnKeyDown(KeyEventArgs e)
- {
- base.OnKeyDown(e);
- if (e.KeyCode == Keys.Delete)
- {
- this.BindMe = DBNull.Value;
- }
- }
- protected override void OnCloseUp(EventArgs eventargs)
- {
- base.OnCloseUp(eventargs);
- BindMe = base.Value;
- }
- }
- }
NullableDateTim ePicker.cs
*************** *************** *************** *************** **
Expand|Select|Wrap|Line Numbers
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Windows.Forms;
- using System.Drawing;
- namespace Custom
- {
- public class NullableCalendarColumn : DataGridViewColumn
- {
- public NullableCalendarColumn() : base(new NullableCalendarCell()) { }
- public NullableCalendarColumn(string frm) : base(new NullableCalendarCell(frm)) { }
- public void setValue(string frm)
- {
- base.CellTemplate.Value = frm;
- }
- public override DataGridViewCell CellTemplate
- {
- get { return base.CellTemplate; }
- set
- {
- // Ensure that the cell used for the template is a CalendarCell.
- if (value != null && !value.GetType().IsAssignableFrom(typeof(NullableCalendarCell)))
- {
- throw new InvalidCastException("Must be a NullableCalendarCell");
- }
- base.CellTemplate = value;
- }
- }
- }
- public class NullableCalendarCell : DataGridViewTextBoxCell
- {
- private String baseFormat = "MM/dd/yyyy";
- public NullableCalendarCell()
- : base()
- {
- // Use the short date format.
- // Change the format here for the normal display.
- this.Style.Format = baseFormat;
- }
- public NullableCalendarCell(String frm)
- : base()
- {
- baseFormat = frm;
- this.Style.Format = frm;
- }
- public String BaseFormat
- {
- get { return baseFormat; }
- set { baseFormat = value; }
- }
- 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);
- NullableCalendarEditingControl ctl = DataGridView.EditingControl as NullableCalendarEditingControl;
- if (this.Value.ToString() == "")
- {
- ctl.BindMe = DBNull.Value;
- }
- else
- {
- ctl.Value = (DateTime)this.Value;
- ctl.Text = this.Value.ToString();
- ctl.EditingControlFormattedValue = this.Value.ToString();
- ctl.IsNull = false;
- ctl.BindMe = (DateTime)this.Value;
- ctl.Left = 100;
- ctl.Name = "toddsctl";
- }
- }
- public override Type EditType
- {
- get
- {
- // Return the type of the editing contol that CalendarCell uses.
- return typeof(NullableCalendarEditingControl);
- }
- }
- public override Type ValueType
- {
- get
- {
- // Return the type of the value that CalendarCell contains.
- return typeof(String);
- }
- }
- public override object DefaultNewRowValue
- {
- get
- {
- // Use the current date and time as the default value.
- return DateTime.Now.ToString();
- }
- }
- public override void DetachEditingControl()
- {
- base.DetachEditingControl();
- if (this.EditedFormattedValue.ToString().Length == 0)
- {
- this.Value = DBNull.Value;
- }
- }
- protected override void OnKeyDown(KeyEventArgs e, int rowIndex)
- {
- base.OnKeyDown(e, rowIndex);
- if (e.KeyCode == Keys.Delete) this.Value = DBNull.Value;
- }
- }
- class NullableCalendarEditingControl : NullableDateTimePicker, IDataGridViewEditingControl
- {
- DataGridView dataGridView;
- private bool valueChanged = false;
- int rowIndex;
- public NullableCalendarEditingControl()
- {
- // change the customformat here for how it shows when editing
- this.Format = this.BaseFormat;
- }
- // Implements the IDataGridViewEditingControl.EditingControlFormattedValue
- // property.
- public object EditingControlFormattedValue
- {
- get { return this.BindMe.ToString(); }
- set
- {
- if (value == null || value as String == "") this.BindMe = DBNull.Value;
- else
- {
- this.BindMe = DateTime.Parse((String)value);
- //this.Value = DateTime.Parse((String)value);
- }
- }
- }
- // Implements the
- // IDataGridViewEditingControl.GetEditingControlFormattedValue method.
- public object GetEditingControlFormattedValue(DataGridViewDataErrorContexts context)
- {
- return EditingControlFormattedValue;
- }
- // Implements the
- // IDataGridViewEditingControl.ApplyCellStyleToEditingControl method.
- public void ApplyCellStyleToEditingControl(DataGridViewCellStyle dataGridViewCellStyle)
- {
- this.Font = dataGridViewCellStyle.Font;
- this.CalendarForeColor = dataGridViewCellStyle.ForeColor;
- this.CalendarMonthBackground = dataGridViewCellStyle.BackColor;
- }
- // Implements the IDataGridViewEditingControl.EditingControlRowIndex property.
- public int EditingControlRowIndex
- {
- get { return rowIndex; }
- set { rowIndex = value; }
- }
- // Implements the IDataGridViewEditingControl.EditingControlWantsInputKey method.
- 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.Tab:
- case Keys.Delete:
- return true;
- default:
- return false;
- }
- }
- // Implements the IDataGridViewEditingControl.PrepareEditingControlForEdit method.
- public void PrepareEditingControlForEdit(bool selectAll)
- {
- // No preparation needs to be done.
- }
- // Implements the IDataGridViewEditingControl.RepositionEditingControlOnValueChange property.
- public bool RepositionEditingControlOnValueChange
- {
- get { return false; }
- }
- // Implements the IDataGridViewEditingControl.EditingControlDataGridView property.
- public DataGridView EditingControlDataGridView
- {
- get { return dataGridView; }
- set { dataGridView = value; }
- }
- // Implements the IDataGridViewEditingControl.EditingControlValueChanged property.
- public bool EditingControlValueChanged
- {
- get { return valueChanged; }
- set { valueChanged = value; }
- }
- // Implements the IDataGridViewEditingControl.EditingPanelCursor property.
- public Cursor EditingPanelCursor
- {
- get { return base.Cursor; }
- }
- 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);
- }
- }
- }