DateTimePicker fields - which one is active?

  • Thread starter Thread starter Richard Lewis Haggard
  • Start date Start date
R

Richard Lewis Haggard

Is it possible to determine which field within a DateTimePicker control's
data collection area is active? If so, how?

I have a client who wants to have the DateTimePicker control accept a date
in DD/MM/YY order. The problem is, this can lead to data loss or extra work
for the user.
Consider this scenario:
The user wants to enter March 31.
The control is initialized to 01/01/07.
The active field is the day field.
The user enters '31'.
The user right cursors to the month field.
The user cursor up arrows.
The month changes to 02.
The date field changes to 28.
The user cursor up arrows again to 03.
Result:
The control now display the 28th of March. The user must left cursor back to
the day of month field and reassert the desired day of month.

Given that this must be a problem that has been inflicted upon our European
neighbors for several years, one would think that there must be some work
around for the problem but I've not heard of any such remedy. My initial
thought is to detect the largest date value entered by the user then restore
that value when the user changes to a month that supports a day of that
value. Any other ideas?
 
Problem solved.
After spending a couple of hours looking, I gave up on getting the actively
being edited field and opted for a slightly different approach that seems to
work.

The control has a ValueChanged event which is only fired when the user
changes a field significantly. If the user types in '1' to the day field,
this event does NOT fire. If a second digit is entered or the user cursors
out of the field the control will fire the event. It is possible to inspect
the control's value to see what changed and I can determine if the user has
changed the day, time, month or year and react accordingly.

The very first time that this event is encountered, I copy the year, month,
day, etc into local variables. On every succeeding time this event is
received, the code inspects the fields to see what has been changed. If a
time or day changes then the new user entered value is saved. If a month or
year is changed then the new value is saved and a check is made to see if
the saved day value is different than the current value and if the saved day
is legal given the new year and month. If legal, then a new DateTime using
that saved day is constructed and loaded into the DateTimePicker's value. As
a result, if the user enters 31 March, moves to the month field, up arrows
to get 30 Apr and up arrows again, the result is 31 May. Because this logic
operates when the year changes too, we catch and properly handle leap years.
 
I have logged that bug with microsoft and expect to see some changes in
their product come NET 4.0 maybe 3.5...How messy was your workaround?
 
Not as bad as one might have feared. Here's the primary code of a version of
the code that went into a dialogbox, er ah I mean form.

public partial class FormDetail : Form
{
private int level = 0; // needed to handle recursive value changed
notification
private int day = 0;
private int month = 0;
private int year = 0;
private int hour = 0;
private int minute = 0;
private int level = 0;


// Handle notification that the date time has changed.
// Keep track of the user's day entry.
// If the month changes to something that is big enough to
// support the user's manually entered day then reassert the user's day.
// This effectively undo's the DateTimePicker's Validate's code's
removal of
// that date.
// Note: the hour and minute stuff is coded rather poorly. It works and
I had
// schedule to keep so I left it in and did not properly optimize it.
private void dateTimePicer_ValueChanged( object sender, EventArgs e )
{
do
{
// The act of changing the value programmatically also fires off
a
// value changed notification. Since we night change the value
// within this method, make sure that we don't have a recursive
// event fire problem.
level++;
if (level != 1)
break;

DateTimePicker dtp = sender as DateTimePicker;
if (dtp == null)
break;

// Did the year or month change?
if (year != dtp.Value.Year || month != dtp.Value.Month)
{
minute = dtp.Value.Minute;
hour = dtp.Value.Hour;
month = dtp.Value.Month;
year = dtp.Value.Year;

// If day is zero then this is the initial change.
if (day == 0)
{
day = dtp.Value.Day;
}
else if (day <= MaxDay())
{
dtp.Value = new DateTime( year, month, day, hour,
minute, dtp.Value.Second );
}
else
{
dtp.Value = new DateTime( year, month, MaxDay(), hour,
minute, dtp.Value.Second );
}
break;
}

// Did the time change? If so, remember it but otherwise we
don't care.
if (minute != dtp.Value.Minute || hour != dtp.Value.Hour )
{
minute = dtp.Value.Minute;
hour = dtp.Value.Hour;
break;
}

// Did the day change? If so, remember it.
if (day != dtp.Value.Day)
day = dtp.Value.Day;

} while (false);
}

level--;
}

private int MaxDay()
{
// Left out for brevity. This code just
// calculates and returns the maximum legal day appropriate
// for the value in the 'month' member.
}
 
Hello Richard,

I am working on a new component, called a FieldPackEditor, which will
provide a great DateTimePicker replacement. Right now, it behaves like
what you describe for the MS DTP. However, it will allow you to get
and set the active field. Also I find that it would be great if my
component could solve the initial concern. I will think about it. Feel
free to post a message in the visualhint's forums about this subject
so that we could discuss about it there.

Best regards,

Nicolas Cadilhac @ VisualHint (http://www.visualhint.com)
Home of Smart FieldPackEditor.Net / DateTimePicker replacement
Home of Smart PropertyGrid for .Net and MFC
Microsoft PropertyGrid Resource List - http://www.propertygridresourcelist.com
 
Back
Top