Binding.

 

 

EXO Binding.

·       Créer une classe MemoireCalculette.

·       Implémenter Inotify

·       Programmer la calculette en utilisant un binding avec la classe ci-dessus.

·       Implémenter un validateur.

 

La technique du binding permet de lier des zones d’affichage (la cible) à des données (la source).

Cette technique fonctionne dans les deux sens

Affichage : sourceàcible.

Saisie :      cibleàsource.

 

La littérature écrit souvent que la source est une classe métier, c’est un raccourci discutable, il sera souvent prudent de transiter par une structure de données intermédiaire.

 

La classe  MemoireCalculette.

 

Commençons ici par construire une classe reflet des trois afficheurs de la calculette :

 

  private double m_x;

  private double m_y;

  private double m_r;

 

Ajoutons des properties telles que :

 

       public double X

        {

            get

            {

                return (this.m_x);

            }

            set

            {

                this.m_x = value;

            }

        }

       

Cependant au cours de nos traitements nous calculerons R. Ce résultat devra être reporté sur le champs texte lié. Cela n’est par défaut pas automatique, notre classe doit pour cela implémenter l’interface Inotify. C’est dommage car notre classe sera polluée par des considérations spécifiques au binding, ce ne peut donc pas être une vraie classe métier.


Déclarons notre intention d’utiliser l’interface Inotify :

 

using System.ComponentModel;

      public class MemoireCalculette: INotifyPropertyChanged

 

Implémentons l’interface:

 

  #region Inotify

 

        public event PropertyChangedEventHandler PropertyChanged;

 

        private void RaisePropertyChanged(string propertyName)

        {

            //lever l'événement change

            if (PropertyChanged != null)

PropertyChanged(this, new PropertyChangedEventArgs(propertyName));

        }

 

   #endregion

 

L’événement PropertyChanged doit être levé chaque fois qu’une donnée est modifiée.

 

La méthode RaisPropertyChanged est une commodité pour lever l’événement en fournissant les bons paramètres Le système de binding est censé s’abonner à l’événement mais la méthode le vérifie.

 

Il ne nous reste plus qu’ a modifier le set de la property R :

 

public double R

        {

            get

            {

                return (this.m_r);

            }

            set

            {

                this.m_r = value;

                this.RaisePropertyChanged("R");

            }

        }

 

Déclarer le binding.

 

 

//une donnée membre pour héberger les informations

//bindées à l'IHM

        private MemoireCalculette laMemoire;

 

        public Page()

        {

            InitializeComponent();

            laMemoire = new MemoireCalculette();

        }// fin constructeur

 

    private void UserControl_Loaded(object sender, RoutedEventArgs e)

        {

            this.DataContext = this.laMemoire;

        }// fin load

 

 

<TextBox x:Name="txtX"  Grid.Column="1" Grid.Row="0" >

            <TextBox.Text>

                <Binding Mode="TwoWay" Path="X"/>

            </TextBox.Text>

 </TextBox>

 

Il existe une syntaxe plus condensée, mais moins claire car n’activant pas intellisense de Visual Studio:

 

Text="{Binding Mode=TwoWay, Path=X}"

Coder les traitements :

 

private void btnPlusClic(object sender, RoutedEventArgs e)

        {

            this.laMemoire.R = this.laMemoire.X + this.laMemoire.Y;

        }//fin btnPlus

 

Ce qui est particulièrement simple. Le traitement ignore superbement l’interface, c’est la justification de la technique du binding.

 

Si vous faites une erreur de saisie, rien n’est signalé, le système se contente d’ignorer l’erreur, voyons comment la signaler.

 

Validateur :

 

La classe ValidationRule de WPF ne semble pas disponible en Silverlight.

 

Vous pouvez télécharger cet ad on :

http://www.codeplex.com/SilverlightValidator

 

Ou lire cet article :

Data Validation with Silverlight3 and the dataform

 

 

Voici cependant le plus simple:

 

Modifier le xaml pour demander la notification des erreurs (cette possibilité n’existe pas en wpf)

 

<Binding Mode="TwoWay" Path="X"

                         NotifyOnValidationError="True"

                         ValidatesOnExceptions="True"/>

 

Dans ce cas les champs fautifs sont entourés de rouge et une info bulle est disponible. Bien noter que l’exception ne se produit qu’une seule fois, si l’opérateur réitère sa demande le traitement prévu est activé. Vous devez donc protéger votre traitement, par exemple (id WPF):

 

private int nbErreur()

        {

            int n = 0;

            if (Validation.GetHasError(this.txtX))

            {

ValidationError v = Validation.GetErrors(this.txtX).First<ValidationError>();

                  MessageBox.Show("erreur de saisie X\n" + v.ErrorContent);

                  n++;

            }

            if (Validation.GetHasError(this.txtY))

            {

ValidationError v = Validation.GetErrors(this.txtY).First<ValidationError>();

                  MessageBox.Show("erreur de saisie Y\n" + v.ErrorContent);

                  n++;

            }

            return (n);

        }

 

private void btnPlusClic(object sender, RoutedEventArgs e)

        {

            if (nbErreur() == 0)

            {

                MessageBox.Show("plus OK");

                this.laMemoire.R = this.laMemoire.X + this.laMemoire.Y;

            }

            else

            {

                MessageBox.Show("plus KO");

                this.txtR.Text = "";

 

Vous pouvez également vous abonner à l’événement erreur :

 

public Page()

        {

            InitializeComponent();

            laMemoire = new MemoireCalculette();

BindingValidationError+=new EventHandler<ValidationErrorEventArgs>(ErreurSaisie);

        }// fin constructeur

 

private void ErreurSaisie(object sender, ValidationErrorEventArgs e)

        {

            this.txtR.Text = "";

            MessageBox.Show(e.Error.ErrorContent.ToString());

        }

 

 

Chapitre suivant.