2
2
using System ;
3
3
using System . Collections . Generic ;
4
4
using System . Linq ;
5
+ using Microsoft . Toolkit . Uwp . UI ;
5
6
using Windows . Foundation ;
6
7
using Windows . System ;
7
8
using Windows . UI . Xaml ;
@@ -16,7 +17,7 @@ public class RectangleSelection_ListViewBase : RectangleSelection
16
17
private ListViewBase uiElement ;
17
18
private ScrollViewer scrollViewer ;
18
19
private SelectionChangedEventHandler selectionChanged ;
19
-
20
+ private DispatcherQueueTimer timer ;
20
21
private Point originDragPoint ;
21
22
private Dictionary < object , System . Drawing . Rectangle > itemsPosition ;
22
23
private List < object > prevSelectedItems ;
@@ -28,6 +29,7 @@ public RectangleSelection_ListViewBase(ListViewBase uiElement, Rectangle selecti
28
29
this . selectionRectangle = selectionRectangle ;
29
30
this . selectionChanged = selectionChanged ;
30
31
itemsPosition = new Dictionary < object , System . Drawing . Rectangle > ( ) ;
32
+ timer = DispatcherQueue . GetForCurrentThread ( ) . CreateTimer ( ) ;
31
33
InitEvents ( null , null ) ;
32
34
}
33
35
@@ -58,19 +60,6 @@ private void RectangleSelection_PointerMoved(object sender, PointerRoutedEventAr
58
60
base . DrawRectangle ( currentPoint , originDragPointShifted , uiElement ) ;
59
61
// Selected area considering scrolled offset
60
62
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
- }
74
63
75
64
foreach ( var item in itemsPosition . ToList ( ) )
76
65
{
@@ -108,17 +97,29 @@ private void RectangleSelection_PointerMoved(object sender, PointerRoutedEventAr
108
97
109
98
private void RectangleSelection_PointerPressed ( object sender , PointerRoutedEventArgs e )
110
99
{
100
+ if ( scrollViewer == null )
101
+ {
102
+ return ;
103
+ }
104
+
111
105
itemsPosition . Clear ( ) ;
106
+
107
+ scrollViewer . ViewChanged -= ScrollViewer_ViewChanged ;
108
+ scrollViewer . ViewChanged += ScrollViewer_ViewChanged ;
109
+
112
110
originDragPoint = new Point ( e . GetCurrentPoint ( uiElement ) . Position . X , e . GetCurrentPoint ( uiElement ) . Position . Y ) ; // Initial drag point relative to the topleft corner
113
111
prevSelectedItems = uiElement . SelectedItems . Cast < object > ( ) . ToList ( ) ; // Save current selected items
114
- var verticalOffset = scrollViewer ? . VerticalOffset ?? 0 ;
112
+
113
+ var verticalOffset = scrollViewer . VerticalOffset ;
115
114
originDragPoint . Y += verticalOffset ; // Initial drag point relative to the top of the list (considering scrolled offset)
116
115
if ( ! e . GetCurrentPoint ( uiElement ) . Properties . IsLeftButtonPressed || e . Pointer . PointerDeviceType == Windows . Devices . Input . PointerDeviceType . Touch )
117
116
{
118
117
// Trigger only on left click, do not trigger with touch
119
118
return ;
120
119
}
121
120
121
+ FetchItemsPosition ( ) ;
122
+
122
123
selectionStrategy = e . KeyModifiers . HasFlag ( VirtualKeyModifiers . Control ) ?
123
124
new InvertPreviousItemSelectionStrategy ( uiElement . SelectedItems , prevSelectedItems ) :
124
125
e . KeyModifiers . HasFlag ( VirtualKeyModifiers . Shift ) ?
@@ -138,13 +139,41 @@ private void RectangleSelection_PointerPressed(object sender, PointerRoutedEvent
138
139
selectionState = SelectionState . Starting ;
139
140
}
140
141
142
+ private void FetchItemsPosition ( )
143
+ {
144
+ var verticalOffset = scrollViewer . VerticalOffset ;
145
+ foreach ( var item in uiElement . Items . ToList ( ) . Except ( itemsPosition . Keys ) )
146
+ {
147
+ var listViewItem = ( FrameworkElement ) uiElement . ContainerFromItem ( item ) ; // Get ListViewItem
148
+ if ( listViewItem == null )
149
+ {
150
+ continue ; // Element is not loaded (virtualized list)
151
+ }
152
+
153
+ var gt = listViewItem . TransformToVisual ( uiElement ) ;
154
+ var itemStartPoint = gt . TransformPoint ( new Point ( 0 , verticalOffset ) ) ; // Get item position relative to the top of the list (considering scrolled offset)
155
+ var itemRect = new System . Drawing . Rectangle ( ( int ) itemStartPoint . X , ( int ) itemStartPoint . Y , ( int ) listViewItem . ActualWidth , ( int ) listViewItem . ActualHeight ) ;
156
+ itemsPosition [ item ] = itemRect ;
157
+ }
158
+ }
159
+
160
+ private void ScrollViewer_ViewChanged ( object sender , ScrollViewerViewChangedEventArgs e )
161
+ {
162
+ if ( ! timer . IsRunning )
163
+ {
164
+ timer . Debounce ( FetchItemsPosition , TimeSpan . FromMilliseconds ( 1000 ) ) ;
165
+ }
166
+ }
167
+
141
168
private void RectangleSelection_PointerReleased ( object sender , PointerRoutedEventArgs e )
142
169
{
143
170
Canvas . SetLeft ( selectionRectangle , 0 ) ;
144
171
Canvas . SetTop ( selectionRectangle , 0 ) ;
145
172
selectionRectangle . Width = 0 ;
146
173
selectionRectangle . Height = 0 ;
147
174
uiElement . PointerMoved -= RectangleSelection_PointerMoved ;
175
+
176
+ scrollViewer . ViewChanged -= ScrollViewer_ViewChanged ;
148
177
uiElement . ReleasePointerCapture ( e . Pointer ) ;
149
178
if ( selectionChanged != null )
150
179
{
0 commit comments