IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Silverlight Discussion :

[SL4] Comment gérer une exception émise depuis un IValueConverter ?


Sujet :

Silverlight

  1. #1
    Membre confirmé Avatar de NeoMan
    Profil pro
    Inscrit en
    Avril 2002
    Messages
    171
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2002
    Messages : 171
    Par défaut [SL4] Comment gérer une exception émise depuis un IValueConverter ?
    Bonjour à tous!

    Je cherche désespérément depuis ce matin une réponse à une question qui me parait pourtant simple : comment gérer une exception émise depuis un IValueConverter ?

    Prenons un cas concret et très simple :
    - Le converteur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
     
        public class GlobalConverter : IValueConverter
        {
            object IValueConverter.Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                return System.Convert.ChangeType(value, targetType, culture);
            }
     
            ...
        }
    - L'utilisation dans le binding :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    <UserControl ...>
        <Grid>
            <TextBox Grid.Column="1" Grid.Row="1" Text="{Binding FloatProperty, Converter={StaticResource GlobalConverter}, Mode=TwoWay, ValidatesOnExceptions=True, NotifyOnValidationError=true}" />        
        </Grid>
    </UserControl>
    En considérant que FloatProperty est de type float; et que je saisie "Valeur non float" dans mon textbox. A la perte du focus mon converter émettra l'exception FormatException : Le format de la chaîne d'entrée est incorrect.; ce qui est tout à fait normal. Seulement cette exception a tendance à planter complètement l'exécution de l'application Silverlight...

    Mais comment faire, pour mettre le TextBox en erreur, avec le classique encadré rouge et un tooltip qui affiche l'erreur (avec un message compréhensible pour l'utilisation, donc que nous pussions gérer) ?

    Merci d'avance pour vos lumières, car hormis une personnalisation du binding lui-même, je ne parviens pas à trouver d'autres solutions techniques!

  2. #2
    Membre éclairé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    436
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2006
    Messages : 436
    Par défaut
    Pour l'encadré rouge :

    Plusieurs cas : ta saisie se retrouve dans un DataGrid, alors il te faudra oeuvrer dans l'event CellValidating et tester toi même la valeur. Si elle n'entre pas dans tes specs, alors tu fais e.IsValid = true (un truc du genre).

    Si tu es dans un textbox, alors tu peux mettre un ValidateError à true dans ton xaml. et dans la propriété bindé sur la propriété Text, dans son setter, tu fais :

    if (value < 0) then throw new exception ("Veuillez saisir une valeur supérieur à zéro") et le textbox récupérera le message qu'il insérera dans l'encadré rouge.



    Je ne met rarement de la validation dans un converter. Un converter est pour moi un moyen de formater une donnée ou définir des propriétés dans l'interface avec des trucs comme ConverterBooleanToVisibility.

    Pour ne pas planter tu peux mettre ton code du converter dans un try catch et gérer l'exception avec un return nothing dans le catch par exemple. Il faut que tu test ton type de donnée entrante car si tu bind sur un objet, si jamais ta variable/property (comme tu veux) passé dans le converter est à Null / Nothing (c#/vb) alors ta conversion peux lever une exception.

    Par exemple : (je risque de mixer vb et c# c'est juste pour exemple car ça fait 6, 7 mois que je ne fais plus que du vb.net ...

    Class ConverterBooleanToMessage : ivalueconverter (nom bidon juste pour montrer)
    {

    public Convert(.......................)
    {
    -if type of value is boolean then
    --- if (value as boolean)
    ------- return "La commande est Ok"
    --- else
    ------- return "erreur lors de la commande"
    --- end if
    -else
    ----debug.WriteLine("Erreur de type de donnée en entrée")
    -end if
    }
    }


    Une autre solution est de placer ta logique dans le getter de la property que tu bind pour être sur que la valeur d'entrée sera valide et ne fera pas planter ton converter.

    Ca peut être get { if (_maProp = null) _maProp = new Object(); return _maProp; }

  3. #3
    Membre confirmé Avatar de NeoMan
    Profil pro
    Inscrit en
    Avril 2002
    Messages
    171
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2002
    Messages : 171
    Par défaut
    Merci beaucoup pour cette réponse.

    Pour donner un peu de contexte, je ne suis pas en phase de réel développement. Mais c'était plutôt une question de bonne pratique d'architecture.

    Comme toi, je ne suis pas fan de mettre des validations au sein d'un IValueConverter. Je ne parle ici que d'une émission d'exception au sein d'un converter. Cette exception étant généré dans le code du converter OU PAS!

    Je vais être titilleux, mais dans ton exemple, il y a déjà un début de validation avec le "type of". Tu valides que la valeur satisfasse bien le fait que tu attends un booléen. Sinon tu agis en conséquence ici sans émettre d'exception.
    Mais admettons le développeur du converter ne protège pas à fond son code; et cela génère une exception par le système (une NullReferenceException ou une FormatException). Alors dans ce cas, à l'exécution hors débuggage, l'erreur est complètement muette; ce qui est dommage en phase de recettage.

    Donc sans pour autant vouloir mettre des (vraies) règles de validations dans les converter; on est tout de même susceptible d'avoir des exception. C'est pourquoi je me posais la question: comment les rendre visibles.

  4. #4
    Membre éclairé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    436
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2006
    Messages : 436
    Par défaut
    Alors pour qu'en version prod tu puisses être au courant qu'une erreur est survenue dans ton converter, admettons que tu utilises le système de Message, tu peux envoyer un message qui sera intercepté. Une fois intercepté, ton écouteur de message va transmettre via webservice ton erreur et ainsi tu pourras la sauvegarder dans un fichier xml, une base de données etc.

    Pour revenir sur le test typeOf value, c'est juste un automatisme que j'ai gardé car un converter peut servir dans différents contextes :

    ConverterToVisibility :

    if type of value is string then
    -- if value.tostring() = "oui" then return Visibility.Visible
    -- else return visibility.Colapse
    -- end if

    elseif typeof value is integer then
    -- return if((value as integer) = 0, Visibility.Collapse, Visibility.Visible)

    elseif typeof value is datetime then
    -- return if(DateTime.Parse(value.tostring() = datetime.Today), Visibility.Visible, Visibility.Collapse)

    elseif typeof value is boolean
    etc etc etc

    Tu peux même tester la présence d'un parameterconverter qui retournera l'inverse des visibility (collapse au lieu de visible et inversement).

    Dans ce genre de cas je préfère employer le terme de contrôle et non de validation. Car le type peut être bon mais la valeur non valide.

    Par exemple if type of value is integer avec value représentant un age, théoriquement un age néatif n'a pas de sens. Pourtant le type de donnée sera correcte si value = -5. Avec expérience je sais que parfois on a pas le choix de déporter une partie de la validation dans le converter.

    Maintenant, avec expérience quand la validation est obligatoire dans mon converter, si c'est possible,
    je me passe de converter et je rajoute une property de type visibility (pour rester dans notre exemple) dans mon viewmodel et je bind dessus.

    je ne connais pas les meilleurs pratiques mais après avoir utilisé les converter, on a tendance à les utiliser parfois dans des cas où l'on peut s'en passer facilement. Il faut en plus prendre en compte la ré utilisabilité d'un converter donc peut être bien de déporté un code dedans etc.

    Exemple :

    Public ReadOnly Property VisibilityUserControlCoquin
    -- Get
    ---- Return if(_age >= 18, Visibility.Visible, Visibility.Collapase)
    -- End Get
    End property

    Ainsi tu peux directement dans un if faire un appel WS pour loguer une erreur si age est null à un instant t sans passer par message ou autre (ou avec si ta plomberie est au point). Après ça dépend comme toujours du temps devant soit, de l'architecture déjà en place, des pratiques instaurées par ton équipe de développement.

    Pour revenir à l'erreur muette, cela serait beaucoup trop contraignant pour l'utilisateur si ce n'était pas le cas. Imagine un datagrid où chaque cellule de chaque colonne représente une somme d'argent. Une erreur dans le converter t'afficherait nbColonne * NbLignes erreur car le converter sera utilisé pour l'affichage (même à l'initialisation) donc complétement bloquant et contraire à l'expérience utilisateur que doit apporter une RIA.

Discussions similaires

  1. Comment gérer une exception ?
    Par Hydro999 dans le forum R
    Réponses: 2
    Dernier message: 08/09/2010, 16h43
  2. Réponses: 4
    Dernier message: 27/11/2009, 17h08
  3. [C#/SQL] Comment gérer les exceptions d'une Procédure stockée ?
    Par thomas_strass dans le forum Accès aux données
    Réponses: 10
    Dernier message: 06/07/2005, 10h40
  4. Comment appeler une fonction JavaScript depuis Delphi ?
    Par Alfred12 dans le forum Web & réseau
    Réponses: 4
    Dernier message: 17/06/2005, 18h15
  5. Réponses: 2
    Dernier message: 28/08/2003, 00h00

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo