2009-01-22 4 views
1

J'ai un objet TextBox.TextProperty lié à une propriété ViewModel. Dans la liaison, j'ai explicitement défini ValidatesOnExceptions à True.Valide les incendies d'exception, mais le message d'exception n'apparaît pas

En ressources TextBox a ce déclencheur:

<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"/> 

Malheureusement, ma mise en œuvre ne parce que quand je travaille pas tout à fait une exception l'arrière-plan TextBox est mis en évidence avec la couleur Crimson, mais le Le texte de l'info-bulle contient "Une exception a été levée par la cible d'une invocation." au lieu du message que j'ai écrit dans le constructeur d'exceptions.

Avez-vous une suggestion?

Nous vous remercions à l'avance, Marco

Répondre

2

En effet, le code de validation est invoquée par réflexion. Toutes les exceptions interceptées seront enveloppées dans une instance TargetInvocationException. L'exception d'origine sera enregistrée sous la forme InnerException.


Qu'est-ce qui se passe si vous liez à la propriété ValidationError.Exception au lieu de ValidationError.ErrorContext?

+0

Bonne prise Stu! Si une liaison à Path = (Validation.Errors) [0] .Exception, j'obtiens dans l'info-bulle le message entier d'exception. Puis j'ai essayé de lier à: (Validation.Errors) [0] .Exception.InnerException.Message et j'ai enfin obtenu le excitement. Mais maintenant ...le comportement de ValidatesOnExcpetions est-il correct? – Drake

+0

Il semble y avoir quelque chose d'étrange dans votre validation - je pense que vous devez déterminer pourquoi votre exception est enveloppée en premier lieu. La liaison à l'exception interne est un peu fragile car elle va cesser de fonctionner si vous avez des exceptions non emballées. –

0

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

1

Je vais avoir cette même question et je ne vois pas pourquoi dans ma validation de cas est invoqué par la réflexion. Je considère l'une des deux solutions.

D'abord je pense à implémenter un convertisseur pour extraire le InnerException de l'exception ValidationError.Exception si nécessaire. Quelque chose comme ceci:

[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(); 
    } 
} 

J'utilise le convertisseur sur le infobulle:

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

Sinon, je pensais utiliser le UpdateSourceExceptionFilter sur la liaison. J'ai mis en place un filtre comme ci-dessous. Cette solution est un peu difficile à utiliser car vous devez définir la propriété UpdateSourceExceptionFilter dans le code derrière.

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); 
} 

Le convertisseur est simple mais ne modifie que le message affiché. Le filtre est une solution plus complète, mais il est difficile de travailler avec chaque liaison. Tous les commentaires seraient considérablement apprécié!

Merci

Questions connexes