【问题标题】:Auto correction behaviour on XAML bound datetime objects since .NET 4.0?自 .NET 4.0 以来 XAML 绑定日期时间对象的自动更正行为?
【发布时间】:2011-06-14 21:53:56
【问题描述】:

在将应用程序从 .NET 3.5 迁移到 .NET 4.0 时,我遇到了这个特殊问题。

(文化是 nl-BE)

我将这样的文本框(在 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>

现在当这个文本框的内容是(例如)10/12/2000 并且我想将它编辑为 09/03/1981 一些令人讨厌的 自动更正发生,当我将光标放在 2000 年底并开始“退格”远离年份值时(当只有 '2000' 的第一个数字 ('2') 自动留下值时 -包括光标跳转 - 再次更改为 2002)。我可以禁用此自动更正吗?

我似乎找不到具体介绍这种行为的原因。对于货币价值,FormatString=c 也会出现同样的“问题”。

到目前为止我已经尝试过:

  1. 将 FormatString 更改为更明确的内容,例如 {0}{dd/MM/yyyy}(同样的问题:当年份剩下 2 位数时开始自动更正)。
  2. 禁用以下我已添加到我的 App.xaml.cs 的 sn-p:

    FrameworkElement.LanguageProperty.OverrideMetadata(
        typeof(FrameworkElement), 
        new FrameworkPropertyMetadata(XmlLanguage.GetLanguage(
            CultureInfo.CurrentCulture.IetfLanguageTag)));
    

首先包含此 sn-p 的原因:have a look at this link

我在这里遗漏了一些明显的东西吗?我无法在 3.5 中重现这一点。我真的必须推出自己的 ValueConverters 才能使其正常工作吗?这看起来像是从 3.5 sp 1 中引入的 StringFormat 倒退了一步。

DateTimeFormatInfo.CurrentInfo.GetAllDateTimePatterns('d') 的输出看起来确实略有不同,但没有什么可以立即解释这种行为(可能不相关):

.NET 3.5 .NET 4.0 d/MM/yyyy d/MM/yyyy 日/月/年 日/月/年 dd-MM-yy dd-MM-yy dd.MM.yy dd.MM.yy yyyy-MM-dd dd.MMM.yyyy yyyy-MM-dd

【问题讨论】:

标签: c# .net wpf xaml .net-4.0


【解决方案1】:

我现在最终使用了类似的东西,但我会对解决上述问题的其他方法非常感兴趣:

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;
    }
}

【讨论】:

    【解决方案2】:

    好吧,如果您在 PropertyChanged 上自动更正,这种行为是“正常的”。 当您开始退格时,传递给 DateTime 构造函数的值是:

    Screen >> DateTime('|' 是光标位置在每个退格之前

    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
    

    (我认为这可能因您的文化而异,因为 yy-mm-dd 字符串格式)

    我不太明白为什么 new DateTime(20,12,10) 在文本框中为我提供 2020 年。当我使用 DateTime.Parse(20,12,10) 它给我 2012-10-20 (yyyy-mm-dd)。必须有某种我们无法控制的自动转换或解析,除非我们使用自定义 ValueConvertor

    如果您绝对需要“输入时验证”,我认为自定义转换器是一个不错的选择,否则 OnLostFocus 就像您说的那样效果很好。

    顺便说一句,我的文化是美国

    【讨论】:

      【解决方案3】:

      【讨论】:

      • 感谢您的提示!我已经考虑过这一点,这确实可以替代“日期时间”解析文本框,尽管它不能解决我也遇到的类似的 StringFormat / PropertyChanged 货币问题......我觉得我应该滚动真的很奇怪我自己的 ValueConverters 让它正常工作(这是从 3.5sp1 中引入的 StringFormat 退一步)。
      • 但是为什么一定要使用StringFormat,DatePicker已经根据UI Culture正确显示一切。
      猜你喜欢
      • 2011-06-09
      • 1970-01-01
      • 2016-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-22
      • 1970-01-01
      相关资源
      最近更新 更多