AD&D – Another Drag & Drop en WPF

Bonjour à tous, si certains sont tombé ici en cherchant des informations sur le célèbre jeu de rôle Advanced Donjon et Dragon, ils peuvent passer leur chemin, par contre, si des fonctionnalités de drag’n’drop en WPF vous intéresse, ce qui vas suivre vas vous intéresser. Descendez dans le labo et tuez le gobelin Hobo qui garde la porte afin de récupéré le 6éme statuette du Dieu Khewl et ainsi déjouer ses plans démoniaque !

Présentation du Drag’n’Drop

Le drag’n’drop consiste à transporter des informations de manière visuelle à l’aide d’un pointeur. Dans la plupart des cas il s’agira d’une souris, mais si vous avez la chance d’avoir une device tactile, votre doigt pourra également faire ce drag’n’drop. On peut décomposer en 2 le drag’n’drop, le drag, qui consiste à choisir les données, souvent déclenché par le clic gauche de la souris et le drop qui dépose les données, le plus souvent au moment où l’on relâche le bouton gauche de la souris.

L’application

Notre application comprend 3 éléments de type label. Deux représentant des armes un le gobelin Hobo qui garde la porte. Le but étant d’attaquer le gobelin en déplaçant l’arme choisie sur le gobelin. A ce moment-là, le label de Hobo indiquera qu’il a reçu une attaque et quel arme l’a attaqué. Pendant le déplacement une status bar dans le bas se mettra a jours.


Et voici le code XAML, assez simple :

<Window x:Class="DND.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="AD&amp;D - Another Drag And Drop" Height="250" Width="350">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="28"/>
<RowDefinition Height="*" />
<RowDefinition Height="30" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Label Name="data1"
Grid.Row="0" Grid.Column="0"
Content="Rapière" Foreground="CornflowerBlue"  />
<Label Name="data2"
Grid.Row="0" Grid.Column="1"
Content="Fronde" Foreground="Crimson"/>
<Label Name="receiver"
Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2"
Content="Hobo le goblin, endormi devant la porte du laboratoire..."  Foreground="Lime" Background="Black"/>
<StatusBar Name="Status"
Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" >
<StatusBarItem Name="StatusContent" />
</StatusBar>
</Grid>
</Window>

Création du Drag

Pour réaliser le Drag il suffit de rajouter un gestionnaire d’évènement sur le mouse move. Ainsi, si la souris survole l’élément, l’évènement sera déclenché.
Voici à quoi ressemblent nos deux labels après cela :

<Label Name="data1"
 Grid.Row="0" Grid.Column="0"
 Content="Rapière" Foreground="CornflowerBlue"
 MouseMove="pickData_MouseMove" />

 <Label Name="data2"
 Grid.Row="0" Grid.Column="1"
 Content="Fronde" Foreground="Crimson"
 MouseMove="pickData_MouseMove" />

Maintenant, il faut coder notre gestionnaire d’évènement

private void pickData_MouseMove(object sender, MouseEventArgs e)
 {
 if (e.LeftButton == MouseButtonState.Pressed)
 {
 DragDropEffects effects;
 DataObject obj = new DataObject();
 Label source = (Label)sender;
 obj.SetData(typeof(string), source.Content);
 effects = DragDrop.DoDragDrop(source, obj, DragDropEffects.Copy | DragDropEffects.Move);
 }
 }

Dans un premier temps on vérifie l’état de la souris afin de savoir sur le bouton gauche est pressé. Si oui on crée un objet de donnée dans lequel on stockera la valeur du label cliqué puis on « copiera » les données dans le presse papier avec la source et des options définissant les actions possible pour le drag’n’drop. Si vous rajouter un Messagebox, vous verrez qu’il s’affichera quand vous cliquerez puis, tout en laissant la souris cliqué, bougerez la souris.

Création du Drop

Pour le drop nous allons utiliser deux évènements, un premier qui est le DragOver et le second le Drop.

Voici le code Xaml du contrôle avec le gestionnaire d’évènements en plus :

<Label Name="receiver"
 Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2"
 Content="Hobo le goblin, endormi devant la porte du laboratoire..."
 Foreground="Lime" Background="Black"
 AllowDrop="True" DragOver="receiver_DragOver" Drop="receiver_Drop"/>

Le premier sera utilisé pour notifier dans la statusbar l’action qui va se produire, dans le cas ou le presse papier contient des données et que le type de donnée est celui accepté.

private void receiver_DragOver(object sender, DragEventArgs e)
 {
 if (e.Data.GetDataPresent(typeof(string)))
 this.StatusContent.Content = "Action : Hobbo vas se prendre un coup...";
 else
 e.Effects = DragDropEffects.None;
 }

Dans le second on récupère les données et on met a jours le label ainsi que la statusbar dans le cas ou des données du bon type sont présente dans le presse papier.

private void receiver_Drop(object sender, DragEventArgs e)
 {
 if (e.Data.GetDataPresent(typeof(string)))
 {
 e.Effects = DragDropEffects.Copy;
 string weapon = (string)e.Data.GetData(typeof(string));
 this.receiver.Content += ("\n... se prend un coup de " + weapon);
 this.StatusContent.Content = "";
 }
 else
 e.Effects = DragDropEffects.None;
 }

Résultat

Voici ce que cela nous donne, dans une petite vidéo de 20 secondes :

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s