I'm a recent convert to the CSLA framework. I have use cases where my users will want to enter a null date or skip over a field that might contain a date. Is it necessary to override the datepicker control or textbox and implement SmartDate? Or is there a common solution to the accomplishing this? Thanks in advance.
Renegrin
The approach from Rocky's book is to use TextBox for date/time field. In this approach, SmartDate is empty when the TextBox is empty.
If you are looking for extension to DateTimePicker to support empty SmartDate, the following might help:
http://www.codeproject.com/cs/miscctrl/NullableDateTimePicker.asp
http://www.codeproject.com/cs/miscctrl/DateTimeSlicker.asp
http://www.omnitalented.com/Blog/PermaLink,guid,9ee757fe-a3e8-46f7-ad04-ef7070934dc8.aspx
Regards,
William
Here's a blog post where someone has written a custom NullableDateTimePicker for CSLA..
I contacted the individual that used to have that code and he has since stepped out of development and into management. He didn't have the CSLA implementation version of the code, so here is my implementation of it using his DB Null version as a base.
public partial class SmartDateTimePicker : DateTimePicker {
private const string NullCustomFormat = " ";
public new String CustomFormat { get; set; }
private DateTimePickerFormat _format;
public new DateTimePickerFormat Format {
get { return _format; }
set {
_format = value;
SetFormat();
OnFormatChanged(EventArgs.Empty);
}
}
private Csla.SmartDate _value;
public new Csla.SmartDate Value{
get { return _value; }
set {
_value = value;
SetFormat();
if (value.IsEmpty) {
if (value.EmptyIsMin) {
base.Value = base.MinDate;
} else {
base.Value = base.MaxDate;
}
base.Checked = false;
} else {
base.Value = value.Date;
}
}
}
public SmartDateTimePicker()
:base() {
InitializeComponent();
this.CustomFormat = NullCustomFormat;
base.Format = DateTimePickerFormat.Custom;
}
#region Formating
private void MakeValueNull() {
if (Value.EmptyIsMin) {
this.Value = new Csla.SmartDate(DateTime.MinValue, Value.EmptyIsMin);
} else {
this.Value = new Csla.SmartDate(DateTime.MaxValue, Value.EmptyIsMin);
}
OnValueChanged(EventArgs.Empty);
}
private void MakeValueToday() {
this.Value = new Csla.SmartDate(DateTime.Now, Value.EmptyIsMin);
OnValueChanged(EventArgs.Empty);
}
private void SetFormat() {
System.Globalization.CultureInfo ci = System.Threading.Thread.CurrentThread.CurrentCulture;
System.Globalization.DateTimeFormatInfo dtf = ci.DateTimeFormat;
if (this.Value.IsEmpty) {
base.CustomFormat = this.CustomFormat;
} else {
switch (_format) {
case DateTimePickerFormat.Long:
base.CustomFormat = dtf.LongDatePattern;
break;
case DateTimePickerFormat.Short:
base.CustomFormat = dtf.ShortDatePattern;
break;
case DateTimePickerFormat.Time:
base.CustomFormat = dtf.ShortTimePattern;
break;
case DateTimePickerFormat.Custom:
base.CustomFormat = this.CustomFormat;
break;
}
}
}
#endregion //Formatting
#region Event Processing
protected override void OnKeyUp(KeyEventArgs e) {
if (e.KeyCode == Keys.Delete) {
MakeValueNull();
} else if (e.KeyCode == Keys.Space && base.ContainsFocus) {
//If the user clicks the space bar on the checkbox, it will be checked and needs to be handled
HandleCheckBoxClicked();
}
base.OnKeyUp(e);
}
protected override void WndProc(ref Message m) {
if (m.Msg == 0x215){ //Handle Clicking or Unclicking the checkbox WM_CAPTURECHANGED
HandleCheckBoxClicked();
}
if (m.Msg == 0x55) { //Handle Droping down the Calender Date Time Picker WM_NOTIFYFORMAT
if (this.Value.IsEmpty) {
// Set the value to today if the value is null
// If this isn't done, the DateTimePicker starts with either the Max Value of the Min Value, rather than today
MakeValueToday();
}
}
base.WndProc(ref m);
}
private void HandleCheckBoxClicked() {
if (base.Checked) {
if (this.Value.IsEmpty) {
MakeValueToday();
}
} else {
// Set the value to today if the Box is being Newly checked
MakeValueNull();
}
}
#endregion // Event Processing
}
Copyright (c) Marimer LLC