9
votes

I have a program with two WPF treeviews that allow dragging and dropping between the two. The problem is, it can be annoying to open / close items on the treeviews because moving the mouse just one pixel while holding the left mouse button triggers the drag / drop functionality. Is there some way to specify how far the mouse should move before it's considered a drag / drop?

3

3 Answers

19
votes

There's a system parameter for this. If you have

Point down = {where mouse down event happened}
Point current = {position in the MouseMove eventargs}

then the mouse has moved the minimum drag distance if

Math.Abs(current.X - down.X) >= SystemParameters.MinimumHorizontalDragDistance ||
Math.Abs(current.Y - down.Y) >= SystemParameters.MinimumVerticalDragDistance
1
votes

Just build a little buffer into your code that determines when the drag starts.

  1. flag mouse down
  2. on mouse move - check for mouse down.. if yes, check to see if its moved farther than whatever buffer you specify (3 pixels is probably good)
  3. if it has, start the drag.
1
votes

Following this article for Drag and Drop implementation, you would have to handle 2 mouse events in order to delay the dragging until the mouse has moved a certain distance. First, add a handler for PreviewMouseDown which stores the initial mouse position relative to your control. Don't use the MouseDown event because it is a bubbling event and may have been handled by a child control before reaching your control.

public class DraggableControl : UserControl
{
  private Point? _initialMousePosition;

  public DraggableControl()
  {
    PreviewMouseDown += OnPreviewMouseDown;
  }

  private void OnPreviewMouseDown(object sender, MouseButtonEventArgs e) {
    _initialMousePosition = e.GetPosition(this);
  }

Additionally, handle MouseMove to check the moved distance and eventually initiate the drag operation:

  ...
  public DraggableControl()
  {
    ...
    MouseMove += OnMouseMove;
  }
  ...
  private void OnMouseMove(object sender, MouseEventArgs e)
  {
    // Calculate distance between inital and updated mouse position
    var movedDistance = (_initialMousePosition - e.GetPosition(this)).Length;
    if (movedDistance > yourThreshold)
    {
      DragDrop.DoDragDrop(...);
    }
  }
}