Auto correction behaviour on XAML bound datetime objects since .NET 4.0?
While bringing an application from .NET 3.5 to .NET 4.0 I've run into this peculiar issue.
(culture is nl-BE)
I bind a TextBox like this (in XAML) to a DateTime value with an UpdateSourceTrigger on PropertyChanged (LostFocus works as expected but as-you-type vali开发者_开发知识库dation is required):
<TextBox Height="23" Margin="146,0,105,97.04" Name="txb_Geboortedatum" VerticalAlignment="Bottom">
<TextBox.Text>
<Binding Path="Geboortedatum" StringFormat="d"
UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<ExceptionValidationRule />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
Now when the contents of this textbox is (for example) 10/12/2000 and I want to edit it to be 09/03/1981 some obnoxious auto-correction occurs when i put the cursor at the end of 2000 and start 'backspacing' away the year value (when only the first digit ('2') of '2000' is left the value automatically - including cursor jump - changes to 2002 again). Can I disable this auto-correction?
I can't seem to find what specifically introduced this behaviour. The same 'problem' also occurs with FormatString=c
for currency values.
What I've tried so far:
- Changing the FormatString to something more explicit like
{0}{dd/MM/yyyy}
(same problem: starts auto-correcting when there are 2 digits for year left). Disabling the following snippet I've added to my App.xaml.cs:
FrameworkElement.LanguageProperty.OverrideMetadata( typeof(FrameworkElement), new FrameworkPropertyMetadata(XmlLanguage.GetLanguage( CultureInfo.CurrentCulture.IetfLanguageTag)));
The reasoning for this snippet to be included in the first place: have a look at this link.
Am i missing something obvious here? I can't reproduce this in 3.5. Do I really have to roll my own ValueConverters for getting this to work properly? That looks like a step back from StringFormat
which was introduced in 3.5 sp 1.
Output from DateTimeFormatInfo.CurrentInfo.GetAllDateTimePatterns('d')
does looks slightly different, nothing that would immediately explain the behaviour though (probably unrelated):
.NET 3.5 .NET 4.0 d/MM/yyyy d/MM/yyyy d/MM/yy d/MM/yy dd-MM-yy dd-MM-yy dd.MM.yy dd.MM.yy yyyy-MM-dd dd.MMM.yyyy yyyy-MM-dd
I ended up using something like this for now, but I would be extremely interested in other approaches for solving the problem above:
public class CustomDateTimeConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter,
CultureInfo culture)
{
if (value == null) { return ""; }
DateTime dt;
if (DateTime.TryParse(value.ToString(), CultureInfo.CurrentCulture,
DateTimeStyles.None, out dt))
{
return dt.ToShortDateString();
}
return "";
}
public object ConvertBack(object value, Type targettype, object parameter,
CultureInfo culture)
{
if (value == null || value.ToString().Trim().Length==0) { return null; }
string frmt = CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern;
DateTime dt;
if (DateTime.TryParseExact(value.ToString(), frmt,
CultureInfo.CurrentCulture,
DateTimeStyles.None, out dt))
{
return dt;
}
return DependencyProperty.UnsetValue;
}
}
Well, this behavior is 'normal' if you auto-correct on PropertyChanged. When you start backspacing, the value passed to the DateTime constructor is :
Screen >> DateTime ( '|' is the cursor placement before each backspace)
10-12-2000| >> DateTime(200,12,10) >> 10-12-0200
10-12-020|0 >> DateTime(020,12,10) >> 10-12-020
10-12-00|20 >> DateTime(020,12,10) >> 10-12-020
10-12-0|20 >> DateTime(20,12,10) >> 10-12-2020
(I think this can vary with your culture because of the yy-mm-dd string format)
tough i dont quite get why new DateTime(20,12,10) guive the year 2020 for me on the textbox. When i use DateTime.Parse(20,12,10) it guive me 2012-10-20 (yyyy-mm-dd). Ther must be some kind of automatique conversion or parsing that we dont have control over unless we use a custom ValueConvertor
I think a custom converter is a good way to go if you absolutly need 'as-you-type validation', else OnLostFocus works well as you said.
Btw, my culture is en-US
Have you tried DatePicker control?
http://msdn.microsoft.com/en-us/library/system.windows.controls.datepicker.aspx
精彩评论