Skip to content

Commit 2df05fb

Browse files
LeoAndJellyfishyair100
authored andcommitted
perf(Selection): 优化矩形选择性能,减少频繁触发选择事件
引入选择更新定时器以减少在拖动选择时频繁触发SelectionChanged事件,通过批量处理选择更新提升性能。新增pendingSelectedItems和pendingRemovedItems列表暂存待处理项,并在定时器触发时统一处理。
1 parent 3dcf9a2 commit 2df05fb

1 file changed

Lines changed: 36 additions & 2 deletions

File tree

src/Files.App/UserControls/Selection/RectangleSelection_ListViewBase.cs

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ public sealed class RectangleSelection_ListViewBase : RectangleSelection
1919
private ScrollViewer scrollViewer;
2020
private SelectionChangedEventHandler selectionChanged;
2121
private DispatcherQueueTimer timer;
22+
private DispatcherQueueTimer selectionUpdateTimer;
23+
private List<object>? pendingSelectedItems;
24+
private List<object>? pendingRemovedItems;
25+
private bool isSelectionUpdatePending;
2226
private Point originDragPoint;
2327
private Dictionary<object, System.Drawing.Rectangle> itemsPosition;
2428
private List<object> prevSelectedItems;
@@ -32,9 +36,23 @@ public RectangleSelection_ListViewBase(ListViewBase uiElement, Rectangle selecti
3236
this.selectionChanged = selectionChanged;
3337
itemsPosition = [];
3438
timer = DispatcherQueue.GetForCurrentThread().CreateTimer();
39+
selectionUpdateTimer = DispatcherQueue.GetForCurrentThread().CreateTimer();
40+
selectionUpdateTimer.Interval = TimeSpan.FromMilliseconds(8);
41+
selectionUpdateTimer.Tick += SelectionUpdateTimer_Tick;
3542
InitEvents(null, null);
3643
}
3744

45+
private void SelectionUpdateTimer_Tick(object? sender, object e)
46+
{
47+
selectionUpdateTimer.Stop();
48+
if (isSelectionUpdatePending && pendingSelectedItems is not null && selectionChanged is not null)
49+
{
50+
selectionChanged(this, new SelectionChangedEventArgs(pendingRemovedItems ?? [], pendingSelectedItems));
51+
isSelectionUpdatePending = false;
52+
pendingRemovedItems = null;
53+
}
54+
}
55+
3856
private void RectangleSelection_PointerMoved(object sender, PointerRoutedEventArgs e)
3957
{
4058
if (scrollViewer is null)
@@ -102,9 +120,14 @@ private void RectangleSelection_PointerMoved(object sender, PointerRoutedEventAr
102120
var currentSelectedItemsDrag = uiElement.SelectedItems.Cast<object>().ToList();
103121
if (prevSelectedItemsDrag is null || !prevSelectedItemsDrag.SequenceEqual(currentSelectedItemsDrag))
104122
{
105-
// Trigger SelectionChanged event if the selection has changed
106123
var removedItems = selectedItemsBeforeChange.Except(currentSelectedItemsDrag).ToList();
107-
selectionChanged(sender, new SelectionChangedEventArgs(removedItems, currentSelectedItemsDrag));
124+
pendingSelectedItems = currentSelectedItemsDrag;
125+
pendingRemovedItems = pendingRemovedItems is null
126+
? removedItems
127+
: pendingRemovedItems.Union(removedItems).ToList();
128+
isSelectionUpdatePending = true;
129+
selectionUpdateTimer.Stop();
130+
selectionUpdateTimer.Start();
108131
prevSelectedItemsDrag = currentSelectedItemsDrag;
109132
}
110133
}
@@ -192,6 +215,17 @@ private void RectangleSelection_PointerReleased(object sender, PointerRoutedEven
192215

193216
scrollViewer.ViewChanged -= ScrollViewer_ViewChanged;
194217
uiElement.ReleasePointerCapture(e.Pointer);
218+
219+
if (selectionUpdateTimer.IsRunning)
220+
{
221+
selectionUpdateTimer.Stop();
222+
if (isSelectionUpdatePending && pendingSelectedItems is not null && selectionChanged is not null)
223+
{
224+
selectionChanged(this, new SelectionChangedEventArgs(pendingRemovedItems ?? [], pendingSelectedItems));
225+
isSelectionUpdatePending = false;
226+
}
227+
}
228+
195229
if (selectionChanged is not null)
196230
{
197231
// Restore and trigger SelectionChanged event

0 commit comments

Comments
 (0)