简体   繁体   English

自 .NET 4.0 以来 XAML 绑定日期时间对象的自动更正行为?

[英]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.在将应用程序从 .NET 3.5 带到 .NET 4.0 时,我遇到了这个特殊问题。

(culture is nl-BE) (文化是 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 validation is required):我将这样的文本框(在 XAML 中)绑定到 DateTime 值,并在 PropertyChanged 上使用 UpdateSourceTrigger(LostFocus 按预期工作,但需要按您的类型进行验证):

<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).现在,当此文本框的内容为(例如)2000 年 10 月 12 日并且我想将其编辑为09/03/1981时,当我将cursor放在 2000 年底并开始“退格”时,会发生一些令人讨厌的自动更正' 去掉年份值(当只留下 '2000' 的第一个数字 ('2') 时,该值会自动 - 包括 cursor 跳转 - 再次变为 2002)。 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.对于货币值, FormatString=c也会出现同样的“问题”。

What I've tried so far:到目前为止我已经尝试过:

  1. 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).将 FormatString 更改为更明确的内容,例如{0}{dd/MM/yyyy} (同样的问题:当年份剩下 2 位数时开始自动更正)。
  2. Disabling the following snippet I've added to my App.xaml.cs:禁用我添加到我的 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.我无法在 3.5 中重现这一点。 Do I really have to roll my own ValueConverters for getting this to work properly?我真的必须推出自己的 ValueConverters 才能使其正常工作吗? That looks like a step back from StringFormat which was introduced in 3.5 sp 1.这看起来像是从 3.5 sp 1 中引入的StringFormat

Output from DateTimeFormatInfo.CurrentInfo.GetAllDateTimePatterns('d') does looks slightly different, nothing that would immediately explain the behaviour though (probably unrelated):来自DateTimeFormatInfo.CurrentInfo.GetAllDateTimePatterns('d') Output 看起来确实略有不同,但没有什么可以立即解释这种行为(可能不相关):

.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.好吧,如果您在 PropertyChanged 上自动更正,这种行为是“正常的”。 When you start backspacing, the value passed to the DateTime constructor is:当您开始退格时,传递给 DateTime 构造函数的值是:

Screen >> DateTime ( ' | ' is the cursor placement before each backspace )屏幕>>日期时间(' | '是每个退格之前的 cursor 位置)

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) (由于yy-mm-dd字符串格式,我认为这可能会因您的文化而异)

tough i dont quite get why new DateTime(20,12,10) guive the year 2020 for me on the textbox.很难,我不太明白为什么 new DateTime(20,12,10) 在文本框中为我提供 2020 年。 When i use DateTime.Parse(20,12,10) it guive me 2012-10-20 (yyyy-mm-dd).当我使用 DateTime.Parse(20,12,10) 它给我 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除非我们使用自定义 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.我认为自定义转换器是 go 如果你绝对需要'as-you-type validation'的好方法,否则 OnLostFocus 就像你说的那样工作得很好。

Btw, my culture is en-US顺便说一句,我的文化是美国

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM