Question

I've run into a very specific bug with the DateTimePicker control in Windows Forms. The control has a custom format (MM-YYYY -> 01/2010) - the month/year of a credit card. Today is the 29th of September. If a user selects the control, and uses the keyboard to set the month to February, the control will throw an ArgumentOutOfRangeException. There is no such date as 29-Feb-2009. This will also happen on days as the 31st, moving to a month with only 30 days.

It'd be easy enough to handle this by setting the day to '01', however a user can click the calendar to manually select the 30th, and then use the keyboard to select February.

How can this exception be caught, when the input is happening on the GUI and not really in code? We've tried to catch it in the TextChanged event, but that is already too late. The exception is already thrown.

Is there any way to handle this case? It would be nice if the control automatically changed the day to the highest value for that month. Or at least if it passed the exception through an event.

(I'm aware that we could trap the KeyPressed event and set the day to 01 each time, but this feels 'hacky').

Was it helpful?

Solution

If you only want the month and year, it seems to me that you shouldn't be using a DatePicker in the first place... why present the user with a control which includes the day of the month when they shouldn't be using it?

I would suggest that you either use two dropdowns, one for the year and one for the month. That will be familiar to users from just about every online payment page, and will avoid the problem.

EDIT: Okay, to answer the specific question of handling exceptions, you can use the Application.ThreadException event, but I'd try to avoid having to do so if you can.

OTHER TIPS

Could you set the DateTimePicker's ShowUpDown property to true so that the control becomes a spinner rather than a calendar drop-down?

There is no way that you can only enter month/year without the day. If no day is explicitly specified the current day is used. The DateTimePicker needs all the data - it doesnt matter if you hide it behind the mask.

The only way to make the DateTimePicker do this is, typical .NET answer, to write your own class that derives from DateTimePicker and has a custom way of handling input without days. Anyhow, you will not get away without setting the day ...

If I may: I suggest a MaskedTextBox with a mask set to '00/0000' (the credit card format) and then a validation of input.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top