Hello World
Hello World

Reputation: 1437

Dragging and scrolling (WPF)

Okay guys, I have been scratching my head like mad over this issue and have spent a good few hours trying to research how it works but I am yet to find an answer.

Basically the issue I am having is that I have a treeview of folders in my application i.e:

Catalog

  Brands
    Nike
    Adidas
    Lactose


  Styles
    Sandles
    Trainers
    Boots

The issue that I am trying to fix is that when I drag a folder around(This is handled in my DragDropManager class), I am unable to scroll up or down(simply displays a lovely stop sign).

This is a problem if I want to move something from the very top to the very bottom.

The scrolling works fine on its own without the dragging being done.

If anyone wishes to see any part of my code feel free to ask as I am unsure what to actually show you guys.

I have read through a good few articles and am just left scratching my head.

Upvotes: 3

Views: 1551

Answers (1)

SvenG
SvenG

Reputation: 5195

There might be better approaches but what I have done is:

  • During Dragging over your target element (QueryContinueDrag) you check if the control you are over has a scrollviewer in its visual tree.

  • now check if you are near the edge of the scrollviewer, e.g. 10px away.

  • scroll the scrollviewer

Here's some code:

Find associated ScrollViewer:

var _scrollViewerControl = FindVisualChild<ScrollViewer>(treeView);

private childItem FindVisualChild<childItem>(DependencyObject obj)
where childItem : DependencyObject
{
  for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
  {
    DependencyObject child = VisualTreeHelper.GetChild(obj, i);
    if (child != null && child is childItem)
      return (childItem)child;
    else
    {
      childItem childOfChild = FindVisualChild<childItem>(child);
      if (childOfChild != null)
        return childOfChild;
    }
  }
  return null;
}

In QueryContinueDrag determine current Position and delta to scrollviewer:

// as we don't have eventargs here exposing the current mouse position we use the
// win32 API to get the current mouse position
Win32.POINT p;
if (!Win32.GetCursorPos(out p))
{
    return;
}

//this is the point on the screen
Point point = new Point(p.X, p.Y);

//get position relative to scrollViewerControl
Point controlPoint = _scrollViewerControl.PointFromScreen(point);

if (controlPoint.Y < 10 && -10 < controlPoint.Y)
{
    _scrollViewerControl.LineUp();
}
else if (controlPoint.Y > _scrollViewerControl.ViewportHeight - 10 && _scrollViewerControl.ViewportHeight + 10 > controlPoint.Y)
{
    _scrollViewerControl.LineDown();
}

if (controlPoint.X < 10 && -10 < controlPoint.X)
{
    _scrollViewerControl.LineLeft();
}
else if (controlPoint.X > _scrollViewerControl.ViewportWidth - 10 && _scrollViewerControl.ViewportWidth + 10 > controlPoint.X)
{
    _scrollViewerControl.LineRight();
}

Upvotes: 2

Related Questions