Ошибки при конвертации значений - PullRequest
2 голосов
/ 26 февраля 2010

При создании пользовательского IValueConverter для поля, редактируемого пользователем, реализация Convert обычно довольно проста.

Реализация ConvertBack - нет, поскольку (при отсутствии явного правила проверки) она должна справляться с неверным вводом пользователем (например, вводить «hi» в поле числового ввода).

Если во время преобразования возникает ошибка, похоже, нет способа сообщить о конкретной ошибке:

  • ConvertBack не может генерировать исключения (если это происходит, программа завершается).
  • Возврат ошибки ValidationError ничего не делает.
  • Возврат DependencyProperty.UnsetValue (который предлагается в документации) приводит к сбою без вывода сообщений (пользовательский интерфейс с ошибкой не отображается, даже если вы настроили шаблон ошибки).
  • Возвращение исходного неконвертированного значения приводит к отображению интерфейса ошибки, но с вводящим в заблуждение текстом ошибки.

Кто-нибудь знает какой-нибудь лучший способ справиться с подобными вещами?

(Примечание: хотя определение пользовательского ValidationRule сработает, я не думаю, что это хороший ответ, поскольку в любом случае ему придется дублировать логику преобразования для обнаружения ошибки.)

1 Ответ

2 голосов
/ 26 февраля 2010

Вы можете избежать дублирования логики, если первым шагом правила проверки будет вызов преобразователя значений, чтобы выяснить, можно ли использовать проверяемое значение.

Конечно, это связывает ваши правила валидации с вашими конвертерами значений, если только вы не создадите правило валидации, которое ищет привязку, чтобы выяснить, какой конвертер значений используется. Но если вы начнете идти по этому пути, рано или поздно это, вероятно, придет вам в голову, как и многим: «подождите, если я использую MVVM, что я делаю, работая с преобразователями значений?»

Edit:

Если ваша ViewModel реализует IDataErrorInfo, который на самом деле является единственным способом жизни, относительно просто подключить преобразователь значения к установщику свойства без написания большого количества логики проверки, зависящей от свойства.

В вашем классе ViewModel создайте два приватных поля:

Dictionary<string, string> Errors;
Dictionary<string, IValueConverter>;

Создайте их (и заполните второе) в конструкторе. Также для IDataErrorInfo:

public string this[string columnName]
{
    return Errors.ContainsKey(columnName)
       ? Errors[columnName]
       : null;
}

Теперь реализуйте метод, подобный этому:

private bool ValidateProperty(string propertyName, Type targetType, object value)
{
   Errors[propertyName] = null;
   if (!Converters.ContainsKey(propertyName))
   {
      return true;
   }
   try
   {
      object result = Converters[propertyName].ConvertBack(value, targetType, null, null)
      return true;
   }
   catch (Exception e)
   {
      Errors[propertyName] = e.Message;
      return false;
   }
}

Теперь ваш установщик свойств выглядит так:

public SomeType SomeProperty
{
   set
   {
      if (ValidateProperty("SomeProperty", typeof(SomeType), value))
      {
         _SomeProperty = value;
      }
   }
}
...