【问题标题】:ValidatesOnExceptions fires but it doesn't show the exception messageValidatesOnExceptions 触发但它不显示异常消息
【发布时间】:2009-01-22 13:44:21
【问题描述】:

我有一个绑定到 ViewModel 属性的 TextBox.TextProperty。在绑定中,我已将 ValidatesOnExceptions 明确设置为 True

在资源中,TextBox 有这个触发器:

<Trigger Property="Validation.HasError" Value="true">
   <Setter 
      Property="ToolTip"
      Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}"/>
   <Setter TargetName="Border" Property="Background" Value="Crimson"/>

不幸的是,我的实现不能完美运行,因为当我遇到异常时,TextBox 背景会以 Crimson 颜色突出显示,但工具提示文本包含 "异常已被调用。” 而不是我在异常构造函数中写的消息。

你有什么建议吗?

提前谢谢你, 马可

【问题讨论】:

    标签: wpf validation binding


    【解决方案1】:

    这是因为验证代码是通过反射调用的。任何捕获的异常都将包含在TargetInvocationException 实例中。原始异常将存储为此异常的InnerException


    如果绑定到ValidationError.Exception 属性而不是ValidationError.ErrorContext 会发生什么?

    【讨论】:

    • 抓得好斯图!如果绑定到 Path=(Validation.Errors)[0].Exception 我会在工具提示中看到整个异常消息。然后我尝试绑定到: (Validation.Errors)[0].Exception.InnerException.Message ,我终于得到了预期的一个。但是现在……ValidatesOnExcpetions 的行为是否正确?
    • 在您的验证中似乎确实发生了一些奇怪的事情 - 我认为您需要首先弄清楚为什么您的异常被包装。绑定到内部异常有点脆弱,因为如果您有任何未包装的异常,它将停止工作。
    【解决方案2】:

    我遇到了同样的问题,我不明白为什么在我的案例中验证是通过反射调用的。我正在考虑两种解决方案之一。

    首先,我正在考虑实现一个转换器,以便在必要时从 ValidationError.Exception 中提取 InnerException。像这样的:

    [ValueConversion(typeof(ValidationError), typeof(string))]
    public class ErrorContentConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var validationError = (ValidationError)value;
    
            if ((validationError.Exception == null) || (validationError.Exception.InnerException == null))
                return validationError.ErrorContent;
            else
                return validationError.Exception.InnerException.Message;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotSupportedException();
        }
    }
    

    我正在工具提示消息中使用转换器:

    <Trigger Property="Validation.HasError" Value="true">
        <Setter Property="ToolTip"
            Value="{Binding RelativeSource={x:Static RelativeSource.Self},
            Path=(Validation.Errors).CurrentItem, Converter={StaticResource ErrorContentConverter}}"/>
    </Trigger>
    

    另外,我想在 Binding 上使用 UpdateSourceExceptionFilter。我已经实现了一个过滤器,如下所示。这个解决方案使用起来有点麻烦,因为您必须在后面的代码中设置 UpdateSourceExceptionFilter 属性。

    object InnerExceptionFilter(object bindingExpression, Exception exception)
    {
        if (exception.InnerException != null)
        {
            var be = (System.Windows.Data.BindingExpression)bindingExpression;
            var rule = be.ParentBinding.ValidationRules.First(x=>x is ExceptionValidationRule);
            return new ValidationError(rule, be, exception.InnerException.Message, exception.InnerException);
        }
        else
            return exception;
    }    
    usage:
    public MyConstructor()
    {
        myTextBox.GetBindingExpression(TextBox.TextProperty).ParentBinding.UpdateSourceExceptionFilter
            = new UpdateSourceExceptionFilterCallback(InnerExceptionFilter);
    }
    

    转换器很简单,但只会更改显示的消息。过滤器是一个更完整的解决方案,但对每个绑定都不友好。任何 cmets 都会非常感激不尽!

    谢谢

    【讨论】:

      【解决方案3】:

      Path=(Validation.Errors)[0].Exception.InnerException.Message}

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-08-28
        • 1970-01-01
        • 2019-12-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-10-11
        相关资源
        最近更新 更多