WPF Listbox auto scroll while dragging

Artur Carvalho picture Artur Carvalho · Aug 22, 2009 · Viewed 12.1k times · Source

I have a WPF app that has a ListBox. The drag mechanism is already implemented, but when the list is too long and I want to move an item to a position not visible I can't.

For example, the screen shows 10 items. And I have 20 items. If I want to drag the last item to the first position I must drag to the top and drop. Scroll up and drag again.

How can I make the ListBox auto scroll?

Answer

Artur Carvalho picture Artur Carvalho · Aug 22, 2009

Got it. Used the event DragOver of the ListBox, used the function found here to get the scrollviewer of the listbox and after that its just a bit of juggling with the Position.

private void ItemsList_DragOver(object sender, System.Windows.DragEventArgs e)
{
    ListBox li = sender as ListBox;
    ScrollViewer sv = FindVisualChild<ScrollViewer>(ItemsList);

    double tolerance = 10;
    double verticalPos = e.GetPosition(li).Y;
    double offset = 3;

    if (verticalPos < tolerance) // Top of visible list?
    {
        sv.ScrollToVerticalOffset(sv.VerticalOffset - offset); //Scroll up.
    }
    else if (verticalPos > li.ActualHeight - tolerance) //Bottom of visible list?
    {
        sv.ScrollToVerticalOffset(sv.VerticalOffset + offset); //Scroll down.    
    }
}

public static childItem FindVisualChild<childItem>(DependencyObject obj) where childItem : DependencyObject
{
    // Search immediate children first (breadth-first)
    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;
}