Search code examples
wpfdrag-and-dropscrollitemscontrol

WPF Drag-to-scroll doesn't work correctly


I am tying to realize a drag-to-scroll functionality in my application and have problems on my way. Can anybody help me? I have a ScrollViewer and inside it an ItemsControl and within ItemsTemplate I have a UserControl. I want to drag that UserControl within ItemsControl. I want the ScrollViewer to scroll down, when I am dragging to the boundaries of the ItemsControl.

protected override void OnPreviewMouseMove(System.Windows.Input.MouseEventArgs e)
{
    if (this.IsMouseCaptured)
    {
        // Get the new mouse position. 
        Point mouseDragCurrentPoint = e.GetPosition(this);

        if (Math.Abs(mouseDragCurrentPoint.Y - this.ActualHeight) <= 50)
        {
            this._scrollStartOffset.Y += 5;
            _containingScrollViewer.ScrollToVerticalOffset(this._scrollStartOffset.Y);
        }
        if (mouseDragCurrentPoint.Y <= 50)
        {
            this._scrollStartOffset.Y -= 5;
            _containingScrollViewer.ScrollToVerticalOffset(this._scrollStartOffset.Y);
        }
    }
    base.OnPreviewMouseMove(e);
}

When I start dragging by calling DragDrop.DoDragDrop() scrolling don't happens. But when I disable dragging, the ScrollViewer scrolls down dependong on mouse position. Maybe there's something that I don't take into accont about dragging and Capturing the mouse? Thanks for attention. Garegin


Solution

  • When using DragDrop.DoDragDrop(), I use a Sub that Handles the Me.DragOver event (in VB) so it looks as follows. Mind you, my control has a ListBox wrapped in a ScrollViewer.

    Private Sub ListBox_Items_DragOver(ByVal sender As System.Object, ByVal e As System.Windows.DragEventArgs) Handles Me.DragOver
            Dim currentMousePoint As Point = e.GetPosition(_containtingScrollViewer)
            If Math.Abs(currentMousePoint.Y - _containtingScrollViewer.ActualHeight) <= 50 Then
                _containtingScrollViewer.ScrollToVerticalOffset(currentMousePoint.Y + 5)
            End If
            If currentMousePoint.Y <= 50 Then
                _containtingScrollViewer.ScrollToVerticalOffset(currentMousePoint.Y - 5)
            End If
    End Sub
    

    This gives me the ability to scroll whilst dragging items. You can tweak the tolerances to get better/smoother scrolling as needed.