private void RectangleSelection_PointerMoved(object sender, PointerRoutedEventArgs e) { if (scrollViewer == null) { return; } var currentPoint = e.GetCurrentPoint(uiElement); var verticalOffset = scrollViewer.VerticalOffset; if (selectionState == SelectionState.Starting) { if (!HasMovedMinimalDelta(originDragPoint.X, originDragPoint.Y - verticalOffset, currentPoint.Position.X, currentPoint.Position.Y)) { return; } // Clear selected items once if the pointer is pressed and moved selectionStrategy.StartSelection(); OnSelectionStarted(); selectionState = SelectionState.Active; } if (currentPoint.Properties.IsLeftButtonPressed) { var originDragPointShifted = new Point(originDragPoint.X, originDragPoint.Y - verticalOffset); // Initial drag point relative to the topleft corner base.DrawRectangle(currentPoint, originDragPointShifted, uiElement); // Selected area considering scrolled offset var rect = new System.Drawing.Rectangle((int)Canvas.GetLeft(selectionRectangle), (int)Math.Min(originDragPoint.Y, currentPoint.Position.Y + verticalOffset), (int)selectionRectangle.Width, (int)Math.Abs(originDragPoint.Y - (currentPoint.Position.Y + verticalOffset))); foreach (var item in uiElement.Items.ToList().Except(itemsPosition.Keys)) { var listViewItem = (FrameworkElement)uiElement.ContainerFromItem(item); // Get ListViewItem if (listViewItem == null) { continue; // Element is not loaded (virtualized list) } var gt = listViewItem.TransformToVisual(uiElement); var itemStartPoint = gt.TransformPoint(new Point(0, verticalOffset)); // Get item position relative to the top of the list (considering scrolled offset) var itemRect = new System.Drawing.Rectangle((int)itemStartPoint.X, (int)itemStartPoint.Y, (int)listViewItem.ActualWidth, (int)listViewItem.ActualHeight); itemsPosition[item] = itemRect; } foreach (var item in itemsPosition.ToList()) { try { if (rect.IntersectsWith(item.Value)) { selectionStrategy.HandleIntersectionWithItem(item.Key); } else { selectionStrategy.HandleNoIntersectionWithItem(item.Key); } } catch (ArgumentException) { // Item is not present in the ItemsSource itemsPosition.Remove(item); } } if (currentPoint.Position.Y > uiElement.ActualHeight - 20) { // Scroll down the list if pointer is at the bottom var scrollIncrement = Math.Min(currentPoint.Position.Y - (uiElement.ActualHeight - 20), 40); scrollViewer.ChangeView(null, verticalOffset + scrollIncrement, null, false); } else if (currentPoint.Position.Y < 20) { // Scroll up the list if pointer is at the top var scrollIncrement = Math.Min(20 - currentPoint.Position.Y, 40); scrollViewer.ChangeView(null, verticalOffset - scrollIncrement, null, false); } } }
private void RectangleSelection_PointerMoved(object sender, PointerRoutedEventArgs e) { if (scrollBar == null) { return; } var currentPoint = e.GetCurrentPoint(uiElement); var verticalOffset = scrollBar.Value - uiElement.ColumnHeaderHeight; if (selectionState == SelectionState.Starting) { if (!HasMovedMinimalDelta(originDragPoint.X, originDragPoint.Y - verticalOffset, currentPoint.Position.X, currentPoint.Position.Y)) { return; } if (uiElement.CurrentColumn != null) { uiElement.CancelEdit(); } selectionStrategy.StartSelection(); OnSelectionStarted(); selectionState = SelectionState.Active; } if (currentPoint.Properties.IsLeftButtonPressed) { var originDragPointShifted = new Point(originDragPoint.X, originDragPoint.Y - verticalOffset); // Initial drag point relative to the topleft corner base.DrawRectangle(currentPoint, originDragPointShifted, uiElement); // Selected area considering scrolled offset var rect = new System.Drawing.Rectangle((int)Canvas.GetLeft(selectionRectangle), (int)Math.Min(originDragPoint.Y, currentPoint.Position.Y + verticalOffset), (int)selectionRectangle.Width, (int)Math.Abs(originDragPoint.Y - (currentPoint.Position.Y + verticalOffset))); var dataGridRowsPosition = new Dictionary <DataGridRow, System.Drawing.Rectangle>(); double actualWidth = -1; foreach (var row in dataGridRows) { if (row.Visibility != Visibility.Visible) { continue; // Skip invalid/invisible rows } if (actualWidth < 0) { var temp = new List <DataGridCell>(); DependencyObjectHelpers.FindChildren <DataGridCell>(temp, row); // Find cells inside row actualWidth = temp.Sum(x => x.ActualWidth); // row.ActualWidth reports incorrect width } var gt = row.TransformToVisual(uiElement); var itemStartPoint = gt.TransformPoint(new Point(0, verticalOffset)); // Get item position relative to the top of the list (considering scrolled offset) var itemRect = new System.Drawing.Rectangle((int)itemStartPoint.X, (int)itemStartPoint.Y, (int)actualWidth, (int)row.ActualHeight); itemsPosition[row.DataContext] = itemRect; // Update item position dataGridRowsPosition[row] = itemRect; // Update ui row position } foreach (var item in itemsPosition.ToList()) { try { if (rect.IntersectsWith(item.Value)) { selectionStrategy.HandleIntersectionWithItem(item.Key); } else { selectionStrategy.HandleNoIntersectionWithItem(item.Key); } } catch (ArgumentException) { // Item is not present in the ItemsSource itemsPosition.Remove(item); } } if (currentPoint.Position.Y > uiElement.ActualHeight - 20) { // Scroll down the list if pointer is at the bottom // Check if there is a loaded row outside the viewport var item = dataGridRowsPosition.OrderBy(x => x.Value.Y).SkipWhile(x => x.Value.Y <= verticalOffset + uiElement.ActualHeight).Select(x => x.Key).FirstOrDefault(); if (item == null) { if (dataGridRowsPosition.Any()) { // Last loaded item is fully visible, ge thet next one from bound item source var index = dataGridRowsPosition.OrderBy(x => x.Value.Y).Last().Key.GetIndex(); var source = (System.Collections.IList)uiElement.ItemsSource; uiElement.ScrollIntoView(source[Math.Min(Math.Max(index + 1, 0), source.Count - 1)], null); } } else { uiElement.ScrollIntoView(item.DataContext, null); } } else if (currentPoint.Position.Y < 20) { // Scroll up the list if pointer is at the top // Check if there is a loaded row outside the viewport var item = dataGridRowsPosition.OrderBy(x => x.Value.Y).TakeWhile(x => x.Value.Y + x.Value.Height <= scrollBar.Value).Select(x => x.Key).LastOrDefault(); if (item == null) { if (dataGridRowsPosition.Any()) { // First loaded item is fully visible, ge thet previous one from bound item source var index = dataGridRowsPosition.OrderBy(x => x.Value.Y).First().Key.GetIndex(); var source = (System.Collections.IList)uiElement.ItemsSource; uiElement.ScrollIntoView(source[Math.Min(Math.Max(index - 1, 0), source.Count - 1)], null); } } else { uiElement.ScrollIntoView(item.DataContext, null); } } } }