0

What I want to achieve is a pretty standard thing, I guess: While dragging a row from a DataGrid in WPF, if the mouse cursor reaches the top or bottom edge, the DataGrid should automatically scroll more content into view.

The following however is a bit of a mess due to legacy code that handles the drag/drop functionality. So far I start my scrolling operation from the DataGrid's MouseMove event:

private void DataGrid_MouseMove(object sender, MouseEventArgs e)
{
    ...

            var mouseposition = e.GetPosition(m_DataGrid);
            if (mouseposition.Y < 50)
            {
                dispatcher.Invoke(() => DatagridAutomaticScroll(m_DataGrid, false), DispatcherPriority.Normal);
            }
            else if (mouseposition.Y > (m_DataGrid.Height - 50))
            {
                dispatcher.Invoke(() => DatagridAutomaticScroll(m_DataGrid, true), DispatcherPriority.Normal);
            }
            else
            {
                scrollwatch.Reset();
            }
}

And this is the called method:

private void DatagridAutomaticScroll(DataGrid dataGrid, bool scrolldown)
{
    if (scrollwatch.IsRunning && scrollwatch.ElapsedMilliseconds < 500) return;
    ScrollViewer scroller = GetScrollViewer(dataGrid);

    if (scrolldown)
    {
        // will be implemented later
    }
    else
    {
        if (scroller.VerticalOffset == 0) return;
        scroller.ScrollToVerticalOffset(scroller.VerticalOffset - 1);
        scrollwatch.Restart();
    }
}

The stopwatch timer prevents the scroller from scrolling all the way immediately, however there are two issues with this:

  • The way it is implemented now, the scrollviewer will only scroll as long as the user moves the mouse (since all of this is only called from the MouseMove event).
  • If I put everything into a loop, which scrolls every x ms as long as the mouse is on the edge, this will lock up my GUI.

I'm not quite sure how to solve this. Starting a new thread is impossible, since I don't think it will have access to GUI controls (also it seems counter intuitive to start a thread for a simple scrolling operation.)

Roland Deschain
  • 2,211
  • 19
  • 50
  • ever heard of timers? DispatcherTimer will do – ASh Oct 24 '19 at 09:48
  • @ASh thx, I will read into it. What I was wondering is: is there a 'standard' way of doing this, or is this feasible as long as it works? – Roland Deschain Oct 24 '19 at 09:51
  • An auto scrolling datagrid is inherently not "standard". Start your timer when the mouse goes over the area you want. Stop when it leaves. A slider has two repeatbuttons at each end and also as what looks like the track on either side of the thumb. You could go find those inside the datagrid and hook events to those rather than work out where the mouse is in the datagrid. – Andy Oct 24 '19 at 10:05
  • 1
    Maybe consider a storyboard or animation controlling the actual movement. – Andy Oct 24 '19 at 10:13

0 Answers0