(Print this page)

Limiting date selection in the DateTimePicker control
Published date: Thursday, April 27, 2017
On: Moer & Éric Moreau's web site

We are specifically talking about Windows Forms this month. One question that comes back every once in a while in forums is how to limit the selection of dates in the DateTimePicker control. I have often see people answering that the control itself cannot do much and the way to go is to validate after the selection. This is far from being the ideal solution!

I have seen this question asked once again lately on Experts Exchange. One of the great experts there named Ark provided a really neat solution that I want to share with you.

Downloadable code

I will not lie to you, 99% of the code of this month is not from me. The code is provided in both VB and C#. the solution was created using Visual Studio 2017 but can surely be used in older version as well.

All the code written by Ark won’t be posted here. You really need to download it to be able to play with it and test it and eventually adopt it because the new features added to the control are pretty damn cool.

What are we talking about?

Very often when you are asking a user to pick a date, some dates are not available. Of course, the control already support MinDate and MaxDate but what about weekends, holidays and other dates your business rules might limit?

The intrinsic DateTimePicker control does not support these features. Ark’s extension does. The following sections will show you how to use the main features of the extension.

Figure 1: The new DateTimePicker in action

As you can see in figure 1, the dates that are not valid are shown in dark gray with a gray background. The cursor is also modified when you hover an invalid date.

If you are really curious, you can dig into Ark’s code and find out that a bunch of API calls are required to achieve that. This is surely for a long time, the proposed solutions in forums were saying to validate the selected date instead of preventing the user from doing an invalid selection.

New property - RestrictBefore

I like to use this feature in conjunction with MinDate. One thing I don’t like about MinDate is that all dates before the MinDate are just not visible at all. The calendar might look a bit strange if your MinDate is one of the last day of the month.

RestrictBefore will gray out all the dates before that date.

What I like to do is to set the RestrictBefore to the exact date I need and set the MinDate to the first day of the month so my calendar does not look weird.

This example is showing how to set the RestrictBefore property to 7 days before today.

'prevent dates older than 7 days from today
Dim dtmMin As DateTime = DateTime.Today.AddDays(-7)
DatePickerEx1.RestrictBefore = dtmMin
DatePickerEx1.MinDate = New DateTime(dtmMin.Year, dtmMin.Month, 1)
//prevent dates older than 7 days from today
DateTime dtmMin = DateTime.Today.AddDays(-7);
datePickerCSEx1.RestrictBefore = dtmMin;
datePickerCSEx1.MinDate = new DateTime(dtmMin.Year, dtmMin.Month, 1);

New Property – RestrictAfter

This one works exactly like RestrictBefore. I also like to set the MaxDate property to the last day of the month.

For example, the following lines set the RestrictAfter property to 3 months from today.

'Prevent dates further than 3 months from today
Dim dtmMax As DateTime = DateTime.Today.AddMonths(3)
DatePickerEx1.RestrictAfter = dtmMax
DatePickerEx1.MaxDate = New DateTime(dtmMax.Year, dtmMax.Month, DateTime.DaysInMonth(dtmMax.Year, dtmMax.Month))
//Prevent dates further than 3 months from today
DateTime dtmMax = DateTime.Today.AddMonths(3);
datePickerCSEx1.RestrictAfter = dtmMax;
datePickerCSEx1.MaxDate = new DateTime(dtmMax.Year, dtmMax.Month, DateTime.DaysInMonth(dtmMax.Year, dtmMax.Month));

New Property – RestrictedDaysOfWeek

Sometimes your business rules will require that some days of week are not valid.

For example, you might want to prevent users from selecting weekends. This is exactly what this line is doing:

'prevent weekends
DatePickerEx1.RestrictedDaysOfWeek.AddRange({DayOfWeek.Saturday, DayOfWeek.Sunday})
//prevent weekends
datePickerCSEx1.RestrictedDaysOfWeek.AddRange(new List<DayOfWeek> { DayOfWeek.Saturday, DayOfWeek.Sunday });

New property – RestrictedDates

In addition to the previous properties which are easily setting the minimum date, the maximum date, and the invalid days of week, you might have to prevent users from selecting specific dates. Holidays are an example of that. RestrictedDates is a list of dates so you can add as many as you need.

This snippet of code will mark the next Friday as invalid.

'prevent a random date - next friday
Dim dtmFriday As DateTime = DateTime.Today
Do while dtmFriday.DayOfWeek <> DayOfWeek.Friday
    dtmFriday = dtmFriday.AddDays(1)
Loop
DatePickerEx1.RestrictedDates.Add(dtmFriday)
//prevent a random date - next friday
DateTime dtmFriday = DateTime.Today;
while (dtmFriday.DayOfWeek != DayOfWeek.Friday)
{
    dtmFriday = dtmFriday.AddDays(1);
}
datePickerCSEx1.RestrictedDates.Add(dtmFriday);

Finding the next available date

Now that we have set a bunch of invalid dates, we might have to find the next valid date (for initialization purpose for example).

This is exactly what this snippet is doing:

'select the first available from today
Dim dtmDate = DateTime.Today
Do While DatePickerEx1.IsDateRestricted(dtmDate)
    dtmDate = dtmDate.AddDays(1)
Loop
DatePickerEx1.Value = dtmDate
//select the first available from today
DateTime dtmDate = DateTime.Today;
while (datePickerCSEx1.IsDateRestricted(dtmDate))
{
    dtmDate = dtmDate.AddDays(1);
}
datePickerCSEx1.Value = dtmDate;

Conclusion

I have published an article in January 2005 on how to extend the DateTimePicker control to handle null values and add nice shortcuts.

This new set of features will make my DateTimePicker extender even more useful for users.


(Print this page)