Функция автоматической коррекции на объектах datetime, связанных с XAML, с .NET 4.0?

Привлекая приложение из .NET 3.5 в .NET 4.0, я столкнулся с этой необычной проблемой.

(культура - nl-BE)

Я привязываю TextBox как это (в XAML) к значению DateTime с помощью UpdateSourceTrigger в PropertyChanged (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 года и начинаю "отменять" значение года (когда только первая цифра ( "2" ) "2000" оставила значение автоматически - включая курсор - изменения в 2002 снова). Могу ли я отключить эту автоматическую коррекцию?

Я не могу найти то, что конкретно ввело это поведение. Эта же "проблема" также встречается с FormatString=c для значений валюты.

Что я пробовал до сих пор:

  • Изменение FormatString на нечто более явное, как {0}{dd/MM/yyyy} (та же проблема: начинается автокоррекция, когда на год осталось 2 цифры).
  • Отключение следующего фрагмента, который я добавил в свой App.xaml.cs:

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

Причины для включения этого фрагмента в первую очередь: посмотреть эту ссылку.

Я пропустил что-то очевидное здесь? Я не могу воспроизвести это в 3.5. Действительно ли мне нужно перевернуть мои собственные ValueConverters, чтобы заставить это работать правильно? Это выглядит как шаг назад от StringFormat, который был введен в 3.5 sp 1.

Результат из DateTimeFormatInfo.CurrentInfo.GetAllDateTimePatterns('d') выглядит несколько иначе, ничего, что бы сразу объяснить поведение, хотя (возможно, не связано):

.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

Ответ 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. Когда вы начинаете backspacing, значение, переданное конструктору DateTime, равно:

Экран → 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)

Жестко, я не понимаю, почему новый DateTime (20,12,10) представляет мне 2020 год для меня в текстовом поле. Когда я использую DateTime.Parse(20,12,10), он должен получить меня 2012-10-20 (гггг-мм-дд). Ther должно быть своего рода автоматическое преобразование или синтаксический анализ, который мы не контролируем, если мы не используем собственный ValueConvertor

Я думаю, что пользовательский конвертер - это хороший способ, если вы абсолютно нуждаетесь в проверке типа "как есть" , иначе OnLostFocus работает хорошо, как вы сказали.

Btw, моя культура en-US