У меня есть TextBox.TextProperty, привязанный к свойству ViewModel. В привязке я явно установил ValidatesOnExceptions в Правда.
В ресурсах 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 выделяется цветом малиновый, но текст всплывающей подсказки содержит «Исключение было выброшено целью вызова». вместо сообщения, которое я написал в конструкторе исключения.
У вас есть какие-либо предложения?
Заранее спасибо, Марко





Это связано с тем, что код проверки вызывается через отражение. Любые перехваченные исключения будут заключены в экземпляр TargetInvocationException. Исходное исключение будет сохранено как InnerException этого исключения.
Что произойдет, если вы привяжетесь к свойству ValidationError.Exception вместо ValidationError.ErrorContext?
Кажется, что в вашей проверке действительно происходит что-то странное - я думаю, вам нужно понять, почему ваше исключение вообще обертывается. Привязка к внутреннему исключению немного хрупкая, потому что она перестанет работать, если у вас есть какие-либо развернутые исключения.
Путь = (Validation.Errors) [0] .Exception.InnerException.Message}
У меня такая же проблема, и я не понимаю, почему в моем случае проверка вызывается через отражение. Я рассматриваю одно из двух решений.
Сначала я подумываю реализовать преобразователь для извлечения InnerException из ValidationError.Exception, когда это необходимо. Что-то вроде этого:
[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>
В качестве альтернативы я решил использовать 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);
}
Конвертер прост, но меняет только отображаемое сообщение. Фильтр - более полное решение, но с ним неудобно работать с каждой привязкой. Любые комментарии будут оценены сильно!
Спасибо
Хороший улов, Стю! Если привязка к Path = (Validation.Errors) [0] .Exception, я получаю во всплывающей подсказке все сообщение об исключении. Затем я попытался выполнить привязку к: (Validation.Errors) [0] .Exception.InnerException.Message и наконец получил ожидаемое. Но теперь ... правильно ли ведет себя ValidatesOnExcpetions?