27/10/2012

[XAML] Bubbling, Tunneling et Konami

Allez aujourd'hui on fait un tout petit topo technique sur une particularité XAML à savoir le bubbling et le tunneling et ensuite on va voir une mise en application ludique et amusante.

Alors on commence par le point théorique.
Lorsque que l'on gère les événements en XAML, on va utiliser 3 types différents d'événements routés

Les événements directs, les événements de type bulle (bubbling) et les événements de type tunnel (tunneling).

Donc pour illustrer rapidement ces trois concepts, on part du postulat que vous avec ceci :

<Grid x:Name="myGrid">
  <StackPanel x:Name="myStackPanel">
    <TextBox x:Name="myTextBox"/>          
  </StackPanel>
</Grid>

Evénements directs

Ici rien de nouveau neuf, on est sur ce qu'il a de plus classique comme cela était géré avec les Forms (Win ou Web). En exemple :

<Grid x:Name="myGrid">
  <StackPanel x:Name="myStackPanel">
    <TextBox x:Name="myTextBox" TextChanged="myTextBox_TextChanged"/>          
  </StackPanel>
</Grid>
Ici l'événement levé sera celui de la modification du texte de la TextBox.


Evénements de type bulle (bubbling)

Le Bubbling va nous permettre de lever un événement ou des événements dans un ordre précis. Ici chaque élément graphique s'abonne au même événement.

<Grid x:Name="myGrid" KeyDown="myGrid_KeyDown" >
  <StackPanel x:Name="myStackPanel" KeyDown="myStackPanel_KeyDown">
    <TextBox x:Name="myTextBox" KeyDown="myTextBox_KeyDown"/>          
  </StackPanel>
</Grid>
Ici le premier élément graphique a lever l'événement sera la TextBox puis le StackPanel et enfin la Grid.


Evénements de type tunnel (tunneling)

Le Tunneling va nous permettre la même granularité :

<Grid x:Name="myGrid" PreviewKeyDown="myGrid_PreviewKeyDown" >
  <StackPanel x:Name="myStackPanel" PreviewKeyDown="myStackPanel_PreviewKeyDown">
    <TextBox x:Name="myTextBox" PreviewKeyDown="myTextBox_PreviewKeyDown"/>          
  </StackPanel>
</Grid>
Ici le premier élément graphique a lever l'événement sera la Grid puis le StackPanel et enfin la TextBox.

Conclusion

D'une manière générale, les événements qui nous permettent de gérer le bubbling sont suffixé de "Down" et ceux pour le tunneling sont préfixé de "Preview". Voilà pour le petit topo. Maintenant on s'amuse...

Coding4Fun

Maintenant qu'on sait faire ça, on fait quoi ? Pour une fois je suis parti d'une idée et pas d'une particularité technique. Donc Aujourd'hui, je vous propose de mettre en place dans nos applications .NET, une fonctionnalité totalement old school, totalement geek, totalement inutile donc totalement indispensable, c'est à dire un Konami Code. C'est parti

On commence par créer notre classe qui va gérer le Code Konami.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;

namespace KonamiWPF
{
    public class KonamiCode
    {
        
        //La belle séquence Konami
        List Konami = new List
        {
            Key.Up, Key.Up,
            Key.Down, Key.Down,
            Key.Left, Key.Right,
            Key.Left, Key.Right,
            Key.B, Key.A
        };

        //notre index pour analyser la séquence
        public int myIndex { get; set; }

        public bool IsCompletedBy(Key myKey)
        {
            //on vérifie que la nouvelle touche pressé correspondent à la série
            if (Konami[myIndex + 1] == myKey)
            {
                myIndex++;
            }

            //mis en place si 3 Key.Up sont rentrés, il ne réinitialise pas analyse de la séquence
            else if (myIndex == 1 && myKey == Key.Up)
            {

            }
            
            // Démarrage de l'analyse de la séquence
            else if (Konami[0] == myKey)
            {
                myIndex = 0;
            }
            else
            {
                myIndex = -1;
            }
            // Si on arrive au bout on renvoie true et on réinitialise
            if (myIndex == Konami.Count -1)
            {
                myIndex = -1;
                return true;
            }
            return false;
        }
    }
}

Maintenant on reprends la même exemple de code XAML :

<Grid x:Name="myGrid" PreviewKeyUp="myGrid_PreviewKeyUp" >
  <StackPanel x:Name="myStackPanel">
    <TextBox x:Name="myTextBox"/>          
  </StackPanel>
</Grid>

Du coup, on fait un petit traitement juste pour vérifier si le Konami est correctement pris en charge.

public partial class MainWindow : Window
    {
        private KonamiCode seq;
        public MainWindow()
        {
            InitializeComponent();
            seq =  new KonamiCode();
        }

        private void myGrid_PreviewKeyUp(object sender, KeyEventArgs e)
        {
            if (seq.IsCompletedBy(e.Key))
            {
                myTextBox.Text = "Konami !!!";
            }
        }
    }

Maintenant je vous laisse faire preuve d'inventivité pour vos créations graphiques et bon code (Konami bien sûr ^^).