Skip to content

Commit efbf622

Browse files
committed
chore: temp workaround for IR-ext selection not working on wasm/droid
1 parent a04afab commit efbf622

File tree

1 file changed

+81
-2
lines changed

1 file changed

+81
-2
lines changed

src/Uno.Toolkit.UI/Behaviors/ItemsRepeaterExtensions.cs

Lines changed: 81 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
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;
26
using System.Collections.Generic;
37
using System.Diagnostics.CodeAnalysis;
48
using System.Linq;
9+
using System.Runtime.InteropServices;
510
using System.Text;
611
using System.Windows.Input;
712
using Microsoft.Extensions.Logging;
@@ -234,12 +239,18 @@ private static void OnSelectionModeChanged(DependencyObject sender, DependencyPr
234239
{
235240
ir.Tapped += OnItemsRepeaterTapped;
236241
ir.ElementPrepared += OnItemsRepeaterElementPrepared;
242+
#if APPLY_UNO12632_WORKAROUND
243+
ir.ElementClearing += OnItemsRepeaterElementClearing;
244+
#endif
237245

238246
SetSelectionSubscription(ir, new CompositeDisposable(
239247
Disposable.Create(() =>
240248
{
241249
ir.Tapped -= OnItemsRepeaterTapped;
242250
ir.ElementPrepared -= OnItemsRepeaterElementPrepared;
251+
#if APPLY_UNO12632_WORKAROUND
252+
ir.ElementClearing -= OnItemsRepeaterElementClearing;
253+
#endif
243254
}),
244255
ir.RegisterDisposablePropertyChangedCallback(ItemsRepeater.ItemsSourceProperty, OnItemsRepeaterItemsSourceChanged)
245256
));
@@ -250,7 +261,10 @@ private static void OnSelectionModeChanged(DependencyObject sender, DependencyPr
250261
try
251262
{
252263
SetIsSynchronizingSelection(ir, true);
253-
264+
265+
#if APPLY_UNO12632_WORKAROUND
266+
ApplyNestedTappedEventBlocker(ir);
267+
#endif
254268
TrySynchronizeDefaultSelection(ir);
255269
SynchronizeMaterializedElementsSelection(ir);
256270
}
@@ -354,7 +368,16 @@ private static void OnItemsRepeaterElementPrepared(ItemsRepeater sender, Microso
354368
var selected = GetSelectedIndexes(sender)?.Contains(args.Index) ?? false;
355369

356370
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);
357379
}
380+
#endif
358381
private static void OnItemsRepeaterItemsSourceChanged(DependencyObject sender, DependencyProperty dp)
359382
{
360383
// When we reach here, ItemsSourceView is already updated.
@@ -603,4 +626,60 @@ internal static void SetItemSelection(ItemsRepeater ir, DependencyObject itemRoo
603626
// todo: generic item is not supported
604627
}
605628
}
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
606685
}

0 commit comments

Comments
 (0)