2011-01-17 1 views
3

У меня есть приложение, которое я недавно преобразовал из проекта VS 2008 .NET 3.5 в проект VS2010 .NET 4. Некоторые из диалоговых окон WPF в проекте ведут себя по-разному после преобразования. Я хотел бы понять, что вызывает эту разницу в поведении, поэтому я могу найти и исправить другие области, которые могут теперь иметь проблемы.Почему установка привязки ведет себя по-разному в .NET 4 vs .NET 3.5

В качестве примера у меня есть диалог MVVM, который позволяет пользователю вводить число. Число хранится внутри как двойное, и пользователь может принимать только диалог, если текст, который они набирают, является действительным двойным. Поэтому у меня есть текстовое поле, связанное с строкой в ​​ViewModel, и кнопка OK, которая включена, только если строка является действительным двойным. Соответствующий Xaml выглядит следующим образом:

<TextBox Text="{Binding ValueString, UpdateSourceTrigger=PropertyChanged}"/> 
<Button IsEnabled="{Binding ValueIsValid}">OK</Button> 

И ViewModel выглядит следующим образом:

class ViewModel : INotifyPropertyChanged 
{ 
    private double actualValue; 
    public string ValueString 
    { 
     get { return actualValue.ToString("G3"); } 
     set 
     { 
      double doubleValue; 
      if (double.TryParse(value, NumberStyles.Float, CultureInfo.CurrentCulture, out doubleValue)) 
      { 
       actualValue = doubleValue; 
       ValueIsValid = true; 
       RaisePropertyChanged("ValueString"); 
      } 
      else 
      { 
       ValueIsValid = false; 
      } 
     } 
    } 

    private bool valueIsValid = true; 
    public bool ValueIsValid 
    { 
     get { return valueIsValid; } 
     set 
     { 
      if (valueIsValid != value) 
      { 
       valueIsValid = value; 
       RaisePropertyChanged("ValueIsValid"); 
      } 
     } 
    } 

    private void RaisePropertyChanged(string property) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(property)); 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
} 

Это работало хорошо в .NET 3.5, но когда он работает на .NET 4 имеет проблему, когда пользователь вводит число. Например, если пользователь вводит «3.05555» в текстовое поле версии .NET 3.5, все в порядке. Однако в версии .NET 4 они могут ввести штраф 3.05, но когда они набирают следующий «5», значение текстового поля изменяется на «3.06», а затем изменяется на «3.07», если они снова нажимают 5. Это как если бы значение возвращалось из свойства ValueString, как только оно было установлено (таким образом, оно было отформатировано как «G3»), но это не имело обыкновение происходить с .NET 3.5.

У меня был взгляд What's New in the .NET Framework 4 (включая What's New in WPF Version 4), но я ничего не нашел об этом изменении.

Если вы хотите это сделать самостоятельно, я создал небольшой пример решения VS2010, вы можете download from here. Проект BindingTest2008 был преобразован из VS 2008 и нацелен на .NET 3.5, а проект BindingTest2010 был создан в VS 2010, ориентированном на .NET 4. В обоих проектах код одинаковый, но проект .NET 4 имеет эту проблему.

Буду признателен за любую помощь в понимании, почему это происходит. Спасибо.

Обновлено: Удаление вызова RaisePropertyChanged("ValueIsValid"); не меняет поведение и набрав неверный номер (например, «3.1a») не промежуточно заменяются последним действительным числом (например, «3.1» в том случае,). Также цифры могут быть введены с более высокой точностью, чем 3 значащие цифры. Например. «3.0545555» - проблема только возникает, когда вещь, которую вы только что набрали, вызовет округление на 3-ей значащей фигуре.

ответ

5

Причина этого различия поведения является:

В 3.5, связывание будет записать новое значение обратно к источнику после каждого нажатия клавиши , без изменения текста в TextBox. Но этот текст может не представляет ценность источника может точно, возможно, потому, что он не включать форматирование и преобразование или , потому что источник изменил значение (в собственности сеттерах) к чему-то еще . Это привело к частым жалобам и жалобам - люди хотели TextBox, чтобы показать значение источника , точно так же, как TextBlock, если связан с тем же свойством с теми же конвертерами и форматированием. В UI должно отображаться то, что на самом деле находится в данных , а не на том, что вводил конечный пользователь.

Чтобы исправить этот класс ошибок в 4.0, связывающая теперь применяет форматирование и преобразование в новое значение Источника в после каждого обновления. (LostFocus привязки уже сделали это в 3.5.) Текстовый текст теперь показывает, что находится в данных, , но это может сделать сложный набор пользователя.

Мы планируем улучшить этот сценарий в следующий выпуск, по крайней мере, двумя способами: 1. Когда текст TextBox заменен пересмотренным строки, вставка точки (курсор), который работал на старой строки может больше не подходит для новой строки . Эвристика, что догадывается, куда положить курсор может быть улучшен. 2. Привязки откроют способ сделать обновления LostFocus (или Явные) с помощью частичной проверки после каждого нажатия клавиши . Форматирование/преобразование применяется только при изменении фокуса, , но пользователь получает обратную связь с оценкой после каждого нажатия клавиши.

  • Сэм (WPF команда)

От «Changed behaviour from .Net 3.5 to .Net 4.0 of WPF TextBox formatting when PropertyChanged is used as UpdateSourceTrigger»

+0

Здесь мы, 4.5, вне, никакого улучшения в поведении, и никакой реальной альтернативы. Редактирование поведения причудливо, если не сказать больше.Может быть, время перевернуть это изменение? –

2

Похоже, проблемы в этой строке:

get { return actualValue.ToString("G3"); } 

версия .Net 4 ведет себя правильно, так как значение получает отформатирован с использованием «G3» формат строки, что означает, что будет 3 значащих цифр в строка результата (3.055 становится 3.06).

Разница между 3.5 и 4 заключается в том, что, по-видимому, система привязки слегка изменилась. В 3.5, когда вызывается средство определения свойства и он вызывает событие PropertyChanged, привязка не получает переоценки (получатель не вызывается). В то время как в .Net 4 после того, как событие PropertyChanged запущено, привязка получает переоценку, то есть получатель свойства IS, и значение, возвращаемое получателем, отображается в текстовом поле.

+0

Это правильно, что причиной округления из-за форматирования в методе GET (который я хочу, так что значение отображается в виде 3 значащих цифр при первом открытии диалога). Однако, даже если я удалю вызов RaisePropertyChanged, проблема все равно произойдет. – Wilka

+0

Да, RaisePropertyChanged не имеет никакого значения. Система привязки работает именно так: она обновляет ценность от источника. Вы можете добиться желаемого поведения, изменив UpdateSourceTrigger привязки к LostFocus. –

+1

Если бы он всегда обновлял значение из источника, то не означает ли это также, что если я наберу «а», он заменит его на последний действительный номер? Увидев, что источник только сохраняет последний действительный номер. – Wilka

Смежные вопросы