diff --git a/src/Eto.Wpf/Forms/Controls/GridHandler.cs b/src/Eto.Wpf/Forms/Controls/GridHandler.cs index ac5d52d63..040d83669 100755 --- a/src/Eto.Wpf/Forms/Controls/GridHandler.cs +++ b/src/Eto.Wpf/Forms/Controls/GridHandler.cs @@ -114,6 +114,12 @@ public abstract class GridHandler : WpfControl Control.FindChild(); + + protected override void HandleDragOver(sw.DragEventArgs e, Eto.Forms.DragEventArgs args) + { + base.HandleDragOver(e, args); + + var scrollViewer = ScrollViewer; + if (scrollViewer == null) + return; + + void ScrollWithIncrement(bool fast, double increment) + { + var now = DateTime.Now; + if (startDragOverTime == null) + { + startDragOverTime = now; + return; + } + + var diff = now - startDragOverTime; + if (diff > TimeSpan.FromSeconds(fast ? DragScrollFastDelay : DragScrollDelay)) + { + startDragOverTime = now; + var oldOffset = scrollViewer.VerticalOffset; + var maxHeight = scrollViewer.ScrollableHeight; + var newOffset = Math.Min(maxHeight, Math.Max(0, oldOffset + increment)); + if (newOffset != oldOffset) + scrollViewer.ScrollToVerticalOffset(newOffset); + } + } + + var headerPart = ShowHeader ? Control.FindChild("PART_ColumnHeadersPresenter") : null; + var headerHeight = headerPart?.ActualHeight ?? 0; + + // scroll up or down when the user drags close to the edge + if (args.Location.Y < headerHeight + DragScrollSize) + { + ScrollWithIncrement(args.Location.Y < headerHeight + DragScrollFastSize, -1); + return; + } + + var height = Control.ActualHeight; + if (scrollViewer.ComputedHorizontalScrollBarVisibility == Visibility.Visible) + { + var child = scrollViewer.FindChild("PART_HorizontalScrollBar"); + height -= child.ActualHeight; + } + + if (args.Location.Y > height - DragScrollSize) + { + ScrollWithIncrement(args.Location.Y > height - DragScrollFastSize, 1); + return; + } + + // not in a drag scroll area, reset + startDragOverTime = null; + } } }