1
- using System ;
1
+ #if __ANDROID__ || NETSTANDARD // (NETSTD contains both wasm+skia; only wasm is needed, and the check is done at runtime)
2
+ #define APPLY_UNO12632_WORKAROUND
3
+ #endif
4
+
5
+ using System ;
2
6
using System . Collections . Generic ;
3
7
using System . Diagnostics . CodeAnalysis ;
4
8
using System . Linq ;
9
+ using System . Runtime . InteropServices ;
5
10
using System . Text ;
6
11
using System . Windows . Input ;
7
12
using Microsoft . Extensions . Logging ;
@@ -234,12 +239,18 @@ private static void OnSelectionModeChanged(DependencyObject sender, DependencyPr
234
239
{
235
240
ir . Tapped += OnItemsRepeaterTapped ;
236
241
ir . ElementPrepared += OnItemsRepeaterElementPrepared ;
242
+ #if APPLY_UNO12632_WORKAROUND
243
+ ir . ElementClearing += OnItemsRepeaterElementClearing ;
244
+ #endif
237
245
238
246
SetSelectionSubscription ( ir , new CompositeDisposable (
239
247
Disposable . Create ( ( ) =>
240
248
{
241
249
ir . Tapped -= OnItemsRepeaterTapped ;
242
250
ir . ElementPrepared -= OnItemsRepeaterElementPrepared ;
251
+ #if APPLY_UNO12632_WORKAROUND
252
+ ir . ElementClearing -= OnItemsRepeaterElementClearing ;
253
+ #endif
243
254
} ) ,
244
255
ir . RegisterDisposablePropertyChangedCallback ( ItemsRepeater . ItemsSourceProperty , OnItemsRepeaterItemsSourceChanged )
245
256
) ) ;
@@ -250,7 +261,10 @@ private static void OnSelectionModeChanged(DependencyObject sender, DependencyPr
250
261
try
251
262
{
252
263
SetIsSynchronizingSelection ( ir , true ) ;
253
-
264
+
265
+ #if APPLY_UNO12632_WORKAROUND
266
+ ApplyNestedTappedEventBlocker ( ir ) ;
267
+ #endif
254
268
TrySynchronizeDefaultSelection ( ir ) ;
255
269
SynchronizeMaterializedElementsSelection ( ir ) ;
256
270
}
@@ -354,7 +368,16 @@ private static void OnItemsRepeaterElementPrepared(ItemsRepeater sender, Microso
354
368
var selected = GetSelectedIndexes ( sender ) ? . Contains ( args . Index ) ?? false ;
355
369
356
370
SetItemSelection ( sender , args . Element , selected ) ;
371
+ #if APPLY_UNO12632_WORKAROUND
372
+ ApplyNestedTappedEventBlocker ( sender , args . Element ) ;
373
+ #endif
374
+ }
375
+ #if APPLY_UNO12632_WORKAROUND
376
+ private static void OnItemsRepeaterElementClearing ( ItemsRepeater sender , Microsoft . UI . Xaml . Controls . ItemsRepeaterElementClearingEventArgs args )
377
+ {
378
+ ClearNestedTappedEventBlocker ( sender , args . Element ) ;
357
379
}
380
+ #endif
358
381
private static void OnItemsRepeaterItemsSourceChanged ( DependencyObject sender , DependencyProperty dp )
359
382
{
360
383
// When we reach here, ItemsSourceView is already updated.
@@ -603,4 +626,60 @@ internal static void SetItemSelection(ItemsRepeater ir, DependencyObject itemRoo
603
626
// todo: generic item is not supported
604
627
}
605
628
}
629
+
630
+ #if APPLY_UNO12632_WORKAROUND
631
+ // note: This issue only happens with ButtonBase on wasm and android where the Tapped event is registered on.
632
+
633
+ private static void ApplyNestedTappedEventBlocker ( ItemsRepeater ir )
634
+ {
635
+ if ( ! IsWasm && ! IsAndroid ) return ;
636
+
637
+ if ( ir . ItemsSourceView is { Count : > 0 } )
638
+ {
639
+ foreach ( var element in ir . GetChildren ( ) )
640
+ {
641
+ ApplyNestedTappedEventBlocker ( ir , element ) ;
642
+ }
643
+ }
644
+ }
645
+ private static void ApplyNestedTappedEventBlocker ( ItemsRepeater ir , DependencyObject itemRoot )
646
+ {
647
+ Console . WriteLine ( $ "@xy droid:{ IsAndroid } , wasm:{ IsWasm } ") ;
648
+ if ( ! IsWasm && ! IsAndroid ) return ;
649
+
650
+ var host = GetUseNestedSelectionHost ( ir )
651
+ ? ( itemRoot . GetFirstDescendant < DependencyObject > ( GetIsSelectionHost ) ?? itemRoot )
652
+ : itemRoot ;
653
+
654
+ if ( host is ButtonBase button )
655
+ {
656
+ button . Tapped -= BlockNestedTappedEvent ;
657
+ button . Tapped += BlockNestedTappedEvent ;
658
+ }
659
+ }
660
+ private static void ClearNestedTappedEventBlocker ( ItemsRepeater ir , DependencyObject itemRoot )
661
+ {
662
+ if ( ! IsWasm && ! IsAndroid ) return ;
663
+
664
+ var host = GetUseNestedSelectionHost ( ir )
665
+ ? ( itemRoot . GetFirstDescendant < DependencyObject > ( GetIsSelectionHost ) ?? itemRoot )
666
+ : itemRoot ;
667
+
668
+ if ( host is ButtonBase button )
669
+ {
670
+ button . Tapped -= BlockNestedTappedEvent ;
671
+ }
672
+ }
673
+ private static void BlockNestedTappedEvent ( object sender , TappedRoutedEventArgs e )
674
+ {
675
+ // prevent the event to bubble up to the ItemsReapter.
676
+ e . Handled = true ;
677
+ }
678
+
679
+ private static bool IsAndroid { get ; }
680
+ #if __ANDROID__
681
+ = true;
682
+ #endif
683
+ private static bool IsWasm { get ; } = RuntimeInformation . IsOSPlatform ( OSPlatform . Create ( "BROWSER" ) ) ;
684
+ #endif
606
685
}
0 commit comments