Search code examples
c#.netwpfscrolllistbox

WPF Listbox auto scroll while dragging


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?


Solution

  • 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;
    }