La propagation événementielle Bubbling en C#

Aller sur Tweened.org

En tant que développeur ou même intégrateur vous avez sans déjà entendu parler de modèle événementiel. Le modèle événementiel d’un langage logique comme par exemple C# est crucial car c’est lui qui permet les interactions utilisateur.

Le modèle événementiel repose sur deux principes importants :

· Le premier est le principe de diffusion d’événements, par exemple lorsque vous cliquez sur un bouton celui-ci diffuse un évènement Click

· Le second principe est celui d’écouteur. Il est bien beau de pouvoir diffuser des évènements, cependant il faut être à l’écoute de ceux-ci pour déclencher une action adéquate. L’objet qui réagit aux événements diffusés est appelé écouteur. En générale, l’écouteur est une méthode comme par exemple la méthode Page_Loaded.

On retrouve ces deux principes dans la vie réelle, voici un exemple :

· Vous décidez de prendre un abonnement à un site Web d’annonces immobilières, le fait de vous abonner fait de vous un écouteur. En effet, à chaque nouvelle annonce, vous recevrez un email d’information concernant le bien immobilier. Vous écoutez le site Web qui agit en tant que diffuseur de l’évènement « nouvelle annonce mise en ligne ». A chaque nouvelle annonce reçue vous décidez ou non de visiter le bien. Ce qui correspond bien à une action en retour.

· Importante mais souvent oubliée cette phase est pourtant très importante : lorsque vous avez trouvé le bien le plus approprié, vous décidez d’arrêter la souscription à ce site, dès lors vous ne recevrez plus d’email. Autrement dit vous supprimez l’écouteur :)

C’est exactement ce qui arrive lorsque vous développez pour Silverlight. C# voici les deux mêmes méthodes écrites différemment, vous remarquerez que l’écriture est nettement plus appropriée et claire, de plus vous aurez une aide à la complétion via l’IntelliSense :

· souscription :

//Diffuseur.Événement += écouteur ;

monRectangle.MouseLeftButtonDown += monRectangle_MouseLeftButtonDown;

· désinscription :

//Diffuseur.Événement -= écouteur ;

monRectangle.MouseLeftButtonDown -= monRectangle_MouseLeftButtonDown;

Il est important de connaitre au moins ces bases car nous allons aborder un point assez spécifique aux langages de haut niveaux. En fait lorsqu’un objet graphique diffuse un événement ce n’est pas forcément l’objet auquel on a souscrit un écouteur. Je m’explique : lorsqu’on crée une série de menus au sein d’une boucle, on ne souhaite peut-être pas à chaque fois ajouter l’écoute du click sur chacun de ces menus. Pourquoi ?

1 – parce que cela est assez gourmant en performance et en mémoire
2 – parce que pour chaque menu il faudra supprimer l’écoute si besoin

Pour éviter de mettre un écouteur sur chaque menu, il suffit simplement de mettre un écouteur sur le conteneur de ceux-ci. En fait lorsque vous souscrivez un écouteur à un conteneur d’objet lorsque l’événement est diffusé vous avez la possibilité de réupérer l’objet source diffusant l’événement au sein du conteneur. je vous ai fait un joli schéma tout en haut.

Je vous donne également un exemple d’utilisation ici :

private void CreateMenu()
{
      var i = 0;
      foreach (string menu in myMenus)
      {
            Debug.WriteLine(menu);
            var monMenu = new Menu();
            //monButton.Content = menu;
            monMenu.Name = menu + "_btn";
            monMenu.Titre = menu;
            monMenu.num = i;
            monMenu.Height = 22;
            monMenu.Margin = new Thickness(0, 10, 0, 0);
            i++;
            myStack.Children.Add(monMenu);

            //ici on évite d'écrire la chose en dessous ::
            //monMenu.MouseLeftButtonUp += new MouseButtonEventHandler(monMenu_MouseLeftButtonUp);

      }

      myStack.MouseLeftButtonUp += new MouseButtonEventHandler(monMenu_MouseLeftButtonUp);
}

void monMenu_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
      //en premier je teste si je clique bien sur un objet de type Menu
      Debug.WriteLine(e.OriginalSource);

      //e.OriginalSource renvoie bien l'objet source qui diffuse l'événement
      Debug.WriteLine("le nom :: " + (e.OriginalSource as Menu).Name);

      int actualMenu = (e.OriginalSource as Menu).num;
      rubTo.ContinueTo((double)(actualMenu * -215));
      rubTween.Start();

}

Il est à noter qu’il est possible d’arrêter la propagation événementielle dans certains cas cela est vraiment pratique car la propriété MouseChildren n’existe pas à priori en C#. Pour arrêter la propagation événementiel il suffira simplement de faire :

void monMenu_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
      //là j'arrête la propagation
      e.Handled = true;
}
Bookmark and Share

Répondre