2

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

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

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

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

有谁知道处理这种事情的更好方法?

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

4

1 回答 1

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;
      }
   }
}
于 2010-02-26T04:43:17.780 回答