值转换期间的错误

时间:2010-02-25 23:46:26

标签: wpf data-binding ivalueconverter

为用户可编辑字段创建自定义IValueConverter时,Convert实现通常非常简单。

ConvertBack实现不是,因为(在没有明确的验证规则的情况下)它必须处理错误的用户输入(例如,在数字输入字段中键入“hi”)。

如果在转换过程中发生错误,似乎没有任何方法可以传达特定错误:

  • 不允许ConvertBack抛出异常(如果是,则程序终止)。
  • 返回ValidationError不会执行任何操作。
  • 返回DependencyProperty.UnsetValue(文档建议)导致静默失败(即使您已设置错误模板,也不会向用户显示错误UI)。
  • 返回原始未转换的值会导致显示错误UI,但会出现误导性错误文本。

有没有人知道处理这类事情的更好方法?

(注意:虽然定义自定义ValidationRule会起作用,但我认为这不是一个好的答案,因为它基本上必须复制转换逻辑才能发现错误。)

1 个答案:

答案 0 :(得分:2)

您可以通过让验证规则的第一步是调用值转换器来查明它验证的值是否可用来避免重复逻辑。

当然,这会将验证规则与您的值转换器相关联,除非您创建一个验证规则来搜索绑定以找出正在使用的值转换器。但是如果你开始沿着这条路走下去,很快就会发生这种情况,就像它对许多人一样,“等等,如果我使用的是MVVM,那么我在做什么,我正在使用价值转换器?”

修改

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