Où l'on commence l'implémentation du contrôle
Pour commencer l'implémentation de ce contrôle, nous allons nous concentrer sur la détection du « gesture » : c'est assez simple, il suffit que l'utilisateur clique sur le contrôle et bouge d'au moins quelques pixels en maintenant le bouton gauche de la souris pour démarrer le drag/drop.
Commençons par créer notre classe :
using System;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows;
namespace Carbenay.Michael.Controls
{
public class DraggableBorder : Border
{
}
}
Il faut ensuite détecter le mouvement de déclenchement :
- Lorsque l'on clique sur l'élément (événement MouseDown) nous allons conserver la position de la souris
- Lorsque l'on bouge la souris sur l'élément (évenement MouseMove) après ce clic, il faudra comparer la position de la souris actuelle par rapport a celle au moment de l'appui et si celle-ci est suffisamment différents – ce « suffisamment » étant défini par un paramètre de Windows – déclencher le drag/drop
- Lorsque le bouton de la souris est relâché au dessus de l'élément (événement MouseUp), le drag/drop est annulé
Pour être sûr de traiter les événements le plus tôt possible, nous n'allons pas vraiment nous connecter aux événements MouseDown, MouseMove, MouseUp mais à leur version « Preview » (pour plus de renseignement sur les événements et leur versions Preview, je vous conseille Application = Code + Markup de Charles Petzold) :
public DraggableBorder()
{
PreviewMouseDown += new MouseButtonEventHandler(MyPreviewMouseDown);
PreviewMouseMove += new MouseEventHandler(MyPreviewMouseMove);
PreviewMouseUp += new MouseButtonEventHandler(MyPreviewMouseUp);
}
// position de la souris sur le MouseDown
private Point _mouseDownPoint = new Point();
// a true si le MouseDown a bien été détecté
// dans le controle
private bool _wasMouseDownInControl = false;
void MyPreviewMouseUp(object sender, MouseButtonEventArgs e)
{
// on "annule" le drag drop
_wasMouseDownInControl = false;
}
void MyPreviewMouseMove(object sender, MouseEventArgs e)
{
// si le bouton gauche de la souris est toujours
// appuyé on regarde si la position actuelle
// est suffisament eloignée de la position de
// départ et si oui, on lance le drag/drop
if (e.LeftButton == MouseButtonState.Pressed
&& _wasMouseDownInControl)
{
Point pos = e.GetPosition(null);
if (SystemParameters.MinimumHorizontalDragDistance <=
Math.Abs(position.X - _mouseDownPoint.X) ||
SystemParameters.MinimumVerticalDragDistance <=
Math.Abs(position.Y - _mouseDownPoint.Y))
{
BeginDrag();
_wasMouseDownInControl = false;
e.Handled = true;
return;
}
}
}
void MyPreviewMouseDown(object sender, MouseButtonEventArgs e)
{
// on enregistre la position de la souris
// pour détecter le mouvement de drag/drop
_mouseDownPoint = e.GetPosition(null);
_wasMouseDownInControl = true;
}
Reste la méthode BeginDrag dont le rôle est de préparer les données et de déclencher le drag/drop. Pour cette première version nous allons faire très simple et créer un objet de donnée avec une ligne de texte simple :
private void BeginDrag()
{
DataObject data = new DataObject();
data.SetData(DataFormats.Text, "Test");
DragDropEffects de = DragDrop.DoDragDrop(this,
data,
DragDropEffects.Copy);
}
Au programme du prochain numéro : qu'est-ce que le DataObject et qu'est-il possible d'y mettre ?