Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

# Nullable DateEdit Control

0.00/5 (No votes)
15 Jun 2003 1  
A Nullable C# DateEdit Control

Sample Image - DateEdit.gif

Introduction

The .NET DateTimePicker (DTP) control is quite good, until you need a nullable date. I recently came to a need for a nullable date and discovered this problem. A good example would be ShippedDate. What should this property contain if the product has not shipped? On a related topic, the DateTime structure doesn't support a null value. .NET Beta's had a DateTime.Empty value but this was removed. I've seen some workarounds with the DTP by using the checkbox to indicate a null value but I would expect some confusion from end users. The DateEdit control is the result of my efforts find a solution to this problem. It shows an empty format "__/__/____" when the value is null. The focus of this control is quick and direct data entry. It currently doesn't provide a drop down calendar, but I have an idea to build an different control for those who need more "eye candy".

Design Considerations

Invalid Dates

Stopping invalid date values from being entered can be difficult. For an example, try entering 2/29/2000 into the DTP. For this reason, I decided not to attempt any validation of the user typing other than allowing only numeric digits. This means that 03/45/____ could be entered into the DateEdit control. To handle this problem, I fire an InvalidDate event from the OnLeave event. This can be used to display a message, or change the back color, or whatever method you prefer to notify the user of invalid values.

Non Nullable DateTime Struct

The DateTime structure does not allow Null values. After spending some time considering writing a NullableDateTime structure, I decided against it. In order for this to work well, it would need to be an exact replacement for the standard DateTime struct. Since a struct cannot be inherited, you will need to implement EVERY method contained in the DateTime struct. One relatively straightforward solution to this problem is to define a new DateTime constant NullValue that equals MinValue ( 01/01/0001 ). This prevents use of MinValue as a valid date but I think I can live with this.

Null Date Persistance

The next issue is how to handle NullValue dates when they are persisted to your database. You could simply persist the 01/01/0001 to the database and remember that this value represents Null. I'm not fond of this solution since someone writing queries against the database might not know this. What would the SQL look like if I wanted to know which orders have not shipped?

Select ... Where ShippedDate Is Null
Select ... Where ShippedDate = 1/1/0001
I think the first SQL looks more logical. Also, if someone is looking at raw columnar data from the table they would see 1/1/0001, which looks like a real date. Null values would be more obvious.

Persisting NullValue (1/1/0001) to the database does have the advantage that no translation to DBNull is necessary.

Persisting Null dates means some additional work. A DateTime struct that supported Null values and would convert to DBNull automatically would be the ideal solution but since DateTime cannot be null, we have to use a workaround. (Read more work for you) The workaround is to add code during database retrieval and persistence to convert NullValue to DBNull.

DateEdit Features

I have incorporated handling for international date formatting and performed "some" testing on this feature. Let me know if you find any bugs.

The DateEdit control is based on the MaskedEdit control. It uses 2 digits for month and day. This means February 5 must be entered 02/05. This adds a couple of sometimes unnecessary keystrokes during date entry.

The IsValid property returns true for valid dates or Null.

Use the Value property to get/set the DateTime value. Note: 1/1/0001 or whatever you decide to use as the NullValue is automatically converted to the blank mask. "__/__/____" depending on your regional settings.

Next Steps

The DateEdit control is designed for simple date entry. Addition of a drop down month calendar would make it more visually appealing. The month calendar can be handy if you're entering dates close to a known date such as +- 1 month from the current date. Entering a birth date in the DTP with any default date by using the month calendar could mean traversing 10, 20, 30 years, 1 month at a time. Not likely to be very fast. Adding a drop down month calendar would mean building a composite control based on the DateEdit, the built-in MonthCalendar and a down arrow button. Let me know what you think. The DateEditEx control would be separate so that if you don't need the added size and overhead of the drop down MonthCalendar then you don't have to use it.

The DateEdit control doesn't currently support time entry. My experience tells me that dates that require time values are best set internally from code. Time entry would add additional typing from the user and I wouldn't expect a high degree of accuracy.

This isn't a perfect solution, workable hopefully. Let me know your ideas for improvement.

History

  • Initial Release: June 16th, 2003

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here