Skip to content

Commit 0d53a0d

Browse files
committed
fix: Prevent repetitive viewport analysis in PointerMoved
1 parent c5c71df commit 0d53a0d

File tree

1 file changed

+49
-15
lines changed

1 file changed

+49
-15
lines changed

src/Files/UserControls/Selection/RectangleSelection_ListViewBase.cs

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System;
33
using System.Collections.Generic;
44
using System.Linq;
5+
using Microsoft.Toolkit.Uwp.UI;
56
using Windows.Foundation;
67
using Windows.System;
78
using Windows.UI.Xaml;
@@ -16,7 +17,7 @@ public class RectangleSelection_ListViewBase : RectangleSelection
1617
private ListViewBase uiElement;
1718
private ScrollViewer scrollViewer;
1819
private SelectionChangedEventHandler selectionChanged;
19-
20+
private DispatcherQueueTimer timer = DispatcherQueue.GetForCurrentThread().CreateTimer();
2021
private Point originDragPoint;
2122
private Dictionary<object, System.Drawing.Rectangle> itemsPosition;
2223
private List<object> prevSelectedItems;
@@ -58,19 +59,6 @@ private void RectangleSelection_PointerMoved(object sender, PointerRoutedEventAr
5859
base.DrawRectangle(currentPoint, originDragPointShifted, uiElement);
5960
// Selected area considering scrolled offset
6061
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)));
61-
foreach (var item in uiElement.Items.ToList().Except(itemsPosition.Keys))
62-
{
63-
var listViewItem = (FrameworkElement)uiElement.ContainerFromItem(item); // Get ListViewItem
64-
if (listViewItem == null)
65-
{
66-
continue; // Element is not loaded (virtualized list)
67-
}
68-
69-
var gt = listViewItem.TransformToVisual(uiElement);
70-
var itemStartPoint = gt.TransformPoint(new Point(0, verticalOffset)); // Get item position relative to the top of the list (considering scrolled offset)
71-
var itemRect = new System.Drawing.Rectangle((int)itemStartPoint.X, (int)itemStartPoint.Y, (int)listViewItem.ActualWidth, (int)listViewItem.ActualHeight);
72-
itemsPosition[item] = itemRect;
73-
}
7462

7563
foreach (var item in itemsPosition.ToList())
7664
{
@@ -109,9 +97,27 @@ private void RectangleSelection_PointerMoved(object sender, PointerRoutedEventAr
10997
private void RectangleSelection_PointerPressed(object sender, PointerRoutedEventArgs e)
11098
{
11199
itemsPosition.Clear();
100+
101+
var verticalOffset = scrollViewer?.VerticalOffset ?? 0;
102+
foreach (var item in uiElement.Items.ToList().Except(itemsPosition.Keys))
103+
{
104+
var listViewItem = (FrameworkElement)uiElement.ContainerFromItem(item); // Get ListViewItem
105+
if (listViewItem == null)
106+
{
107+
continue; // Element is not loaded (virtualized list)
108+
}
109+
110+
var gt = listViewItem.TransformToVisual(uiElement);
111+
var itemStartPoint = gt.TransformPoint(new Point(0, verticalOffset)); // Get item position relative to the top of the list (considering scrolled offset)
112+
var itemRect = new System.Drawing.Rectangle((int)itemStartPoint.X, (int)itemStartPoint.Y, (int)listViewItem.ActualWidth, (int)listViewItem.ActualHeight);
113+
itemsPosition[item] = itemRect;
114+
}
115+
scrollViewer.ViewChanged -= ScrollViewer_ViewChanged;
116+
scrollViewer.ViewChanged += ScrollViewer_ViewChanged;
117+
112118
originDragPoint = new Point(e.GetCurrentPoint(uiElement).Position.X, e.GetCurrentPoint(uiElement).Position.Y); // Initial drag point relative to the topleft corner
113119
prevSelectedItems = uiElement.SelectedItems.Cast<object>().ToList(); // Save current selected items
114-
var verticalOffset = scrollViewer?.VerticalOffset ?? 0;
120+
115121
originDragPoint.Y += verticalOffset; // Initial drag point relative to the top of the list (considering scrolled offset)
116122
if (!e.GetCurrentPoint(uiElement).Properties.IsLeftButtonPressed || e.Pointer.PointerDeviceType == Windows.Devices.Input.PointerDeviceType.Touch)
117123
{
@@ -138,13 +144,41 @@ private void RectangleSelection_PointerPressed(object sender, PointerRoutedEvent
138144
selectionState = SelectionState.Starting;
139145
}
140146

147+
private void ScrollViewer_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
148+
{
149+
if (!e.IsIntermediate)
150+
{
151+
timer.Stop();
152+
timer.Debounce(() =>
153+
{
154+
var verticalOffset = scrollViewer?.VerticalOffset ?? 0;
155+
156+
foreach (var item in uiElement.Items.ToList().Except(itemsPosition.Keys))
157+
{
158+
var listViewItem = (FrameworkElement)uiElement.ContainerFromItem(item); // Get ListViewItem
159+
if (listViewItem == null)
160+
{
161+
continue; // Element is not loaded (virtualized list)
162+
}
163+
164+
var gt = listViewItem.TransformToVisual(uiElement);
165+
var itemStartPoint = gt.TransformPoint(new Point(0, verticalOffset)); // Get item position relative to the top of the list (considering scrolled offset)
166+
var itemRect = new System.Drawing.Rectangle((int)itemStartPoint.X, (int)itemStartPoint.Y, (int)listViewItem.ActualWidth, (int)listViewItem.ActualHeight);
167+
itemsPosition[item] = itemRect;
168+
}
169+
}, TimeSpan.FromSeconds(1));
170+
}
171+
}
172+
141173
private void RectangleSelection_PointerReleased(object sender, PointerRoutedEventArgs e)
142174
{
143175
Canvas.SetLeft(selectionRectangle, 0);
144176
Canvas.SetTop(selectionRectangle, 0);
145177
selectionRectangle.Width = 0;
146178
selectionRectangle.Height = 0;
147179
uiElement.PointerMoved -= RectangleSelection_PointerMoved;
180+
181+
scrollViewer.ViewChanged -= ScrollViewer_ViewChanged;
148182
uiElement.ReleasePointerCapture(e.Pointer);
149183
if (selectionChanged != null)
150184
{

0 commit comments

Comments
 (0)