views:

492

answers:

3

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').

+1  A: 

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

Matt Hamilton
This of course means you still have to set the day to 1 before showing it to the user.
Matt Hamilton
+4  A: 

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.

Jon Skeet
I just tested if it happens when the day is shown to the user, and it does not. So you're right, the wrong control IS in use. But the purpose of me asking the question was to find out if it was possible to handle exceptions that occurred in similar ways? If an exception is generated from UI interaction of a control.
Josh Smeaton
A: 

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.

Ezekiel Rage