2010-02-25 4 views
2

Lors de la création d'un IValueConverter personnalisé pour un champ modifiable par l'utilisateur, l'implémentation de conversion est généralement assez simple. L'implémentation de ConvertBack n'est pas, puisque (en l'absence d'une règle de validation explicite) il doit faire face à une mauvaise entrée de l'utilisateur (par exemple en tapant "hi" dans un champ de saisie numérique).Erreurs lors de la conversion de valeur

Si une erreur se produit lors de la conversion, il ne semble pas être un moyen de communiquer l'erreur spécifique:

  • ConvertBack ne peut pas lancer des exceptions (si elle le fait, le programme se termine).
  • Renvoyer une ValidationError ne fait rien.
  • La restitution de DependencyProperty.UnsetValue (suggérée par les documents) entraîne une défaillance silencieuse (aucune erreur ne s'affiche à l'utilisateur, même si vous avez configuré un modèle d'erreur).
  • La valeur non convertie d'origine provoque l'affichage de l'erreur UI, mais avec un texte d'erreur trompeur.

Est-ce que quelqu'un connaît une meilleure façon de gérer ce genre de chose?

(Note: tout en définissant une ValidationRule personnalisée fonctionnerait, je ne pense pas que ce soit une bonne réponse, car il aurait essentiellement dupliquer la logique de conversion pour découvrir l'erreur de toute façon.)

Répondre

2

Vous pouvez éviter de dupliquer logique en faisant en sorte que la première étape de la règle de validation consiste à appeler le convertisseur de valeur pour savoir si la valeur qu'il valide est même utilisable.

Bien sûr, cela associe vos règles de validation à vos convertisseurs de valeur, à moins que vous ne fassiez une règle de validation qui recherche la liaison pour déterminer quel convertisseur de valeur est utilisé. Mais si vous commencez à suivre cette voie, tôt ou tard, il vous arrivera probablement, comme cela a été le cas pour beaucoup, "attendez, si j'utilise MVVM, qu'est-ce que je fais avec des convertisseurs de valeur?"

Edit:

Si votre ViewModel implémente IDataErrorInfo, qui est vraiment la seule façon de vivre, il est relativement facile de brancher un convertisseur de valeur dans un setter de propriété sans écrire beaucoup de logique de validation spécifique à la propriété.

Dans votre classe ViewModel, créez deux champs privés:

Dictionary<string, string> Errors; 
Dictionary<string, IValueConverter>; 

Créer eux (et remplir la seconde) dans le constructeur. En outre, pour IDataErrorInfo:

public string this[string columnName] 
{ 
    return Errors.ContainsKey(columnName) 
     ? Errors[columnName] 
     : null; 
} 

Maintenant, mettre en œuvre une méthode comme ceci:

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

Maintenant, votre setter de propriété ressemble à ceci:

public SomeType SomeProperty 
{ 
    set 
    { 
     if (ValidateProperty("SomeProperty", typeof(SomeType), value)) 
     { 
     _SomeProperty = value; 
     } 
    } 
} 
+0

Je parle d'une situation où je don Cependant, je ne veux pas du tout définir une règle de validation. Mais oui, vous avez raison que vous pouvez éviter le problème par exemple. définir toutes les propriétés de l'utilisateur dans le ViewModel en tant que chaînes.Mais cela semble aussi un peu extrême, et * aussi * n'aide pas à montrer l'interface utilisateur d'erreur, du moins pas avec les mécanismes intégrés. – Miral

+0

Vous évitez le problème? Pas du tout. Voir ma modification. La seule chose que l'approche que je dessine est la possibilité de définir le convertisseur de valeur sur l'objet de liaison. Je ne peux pas penser à une bonne raison d'attacher des convertisseurs de valeur aux liaisons si vous utilisez un ViewModel. –

Questions connexes