diff --git a/samples/CommunityToolkit.Maui.Sample/Pages/Behaviors/TouchBehaviorPage.xaml b/samples/CommunityToolkit.Maui.Sample/Pages/Behaviors/TouchBehaviorPage.xaml index 09357a500..8f1b88ea8 100644 --- a/samples/CommunityToolkit.Maui.Sample/Pages/Behaviors/TouchBehaviorPage.xaml +++ b/samples/CommunityToolkit.Maui.Sample/Pages/Behaviors/TouchBehaviorPage.xaml @@ -25,7 +25,6 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/samples/CommunityToolkit.Maui.Sample/ViewModels/Behaviors/ItemViewModel.cs b/samples/CommunityToolkit.Maui.Sample/ViewModels/Behaviors/ItemViewModel.cs new file mode 100644 index 000000000..3316dd7fb --- /dev/null +++ b/samples/CommunityToolkit.Maui.Sample/ViewModels/Behaviors/ItemViewModel.cs @@ -0,0 +1,19 @@ +using CommunityToolkit.Mvvm.Input; + +namespace CommunityToolkit.Maui.Sample.ViewModels.Behaviors; + +public partial class ItemViewModel : BaseViewModel +{ + public string Title { get; } + + public ItemViewModel(string title) + { + Title = title; + } + + [RelayCommand] + public Task TapAsync() + { + return Application.Current?.MainPage?.DisplayAlert("Tap", Title, "OK") ?? Task.CompletedTask; + } +} \ No newline at end of file diff --git a/samples/CommunityToolkit.Maui.Sample/ViewModels/Behaviors/TouchBehaviorViewModel.cs b/samples/CommunityToolkit.Maui.Sample/ViewModels/Behaviors/TouchBehaviorViewModel.cs index b2adb9a24..706ce4c3e 100644 --- a/samples/CommunityToolkit.Maui.Sample/ViewModels/Behaviors/TouchBehaviorViewModel.cs +++ b/samples/CommunityToolkit.Maui.Sample/ViewModels/Behaviors/TouchBehaviorViewModel.cs @@ -1,3 +1,4 @@ +using System.Collections.ObjectModel; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; @@ -7,6 +8,8 @@ public partial class TouchBehaviorViewModel : BaseViewModel { [ObservableProperty] int touchCount, longPressCount; + + public ObservableCollection Items { get; } static Task DisplayAlert(string title, CancellationToken token) => Shell.Current.DisplayAlert(title, null, "Ok").WaitAsync(token); @@ -19,6 +22,15 @@ static Task ParentClicked(CancellationToken token) static Task ChildClicked(CancellationToken token) => DisplayAlert("Child Clicked", token); + public TouchBehaviorViewModel() + { + Items = []; + for (var i = 0; i < 50; ++i) + { + Items.Add(new ItemViewModel($"Item {i}")); + } + } + [RelayCommand] async Task MonkeySelected(string? monkey, CancellationToken token) { @@ -42,4 +54,4 @@ void IncreaseLongPressCount() { LongPressCount++; } -} \ No newline at end of file +} diff --git a/src/CommunityToolkit.Maui/Behaviors/ICommunityToolkitBehavior.shared.cs b/src/CommunityToolkit.Maui/Behaviors/ICommunityToolkitBehavior.shared.cs index 0df155889..d81a2988d 100644 --- a/src/CommunityToolkit.Maui/Behaviors/ICommunityToolkitBehavior.shared.cs +++ b/src/CommunityToolkit.Maui/Behaviors/ICommunityToolkitBehavior.shared.cs @@ -21,11 +21,40 @@ internal bool TrySetBindingContextToAttachedViewBindingContext() throw new InvalidOperationException($"{nameof(ICommunityToolkitBehavior)} can only be used for a {nameof(Behavior)}"); } - if (behavior.IsSet(BindableObject.BindingContextProperty) || View is null) + if (View is null) { return false; } + var parent = View.Parent; + var assignBindingContext = behavior.IsSet(BindableObject.BindingContextProperty) is false; + + // If we have a BindingContext, the type is the same as the Views BindingContext and we are inside a CollectionView + // then we can assume that we are recycling views and need to assign the BindingContext again. + if (View.BindingContext?.GetType() == behavior.BindingContext?.GetType()) + { + for (var i = 0; i < 10; i++) + { + if (parent is null) + { + break; + } + + if (parent is CollectionView) + { + assignBindingContext = true; + break; + } + + parent = parent.Parent; + } + } + + if (assignBindingContext is false) + { + return false; + } + behavior.SetBinding(BindableObject.BindingContextProperty, new Binding { Source = View, @@ -33,7 +62,6 @@ internal bool TrySetBindingContextToAttachedViewBindingContext() }); return true; - } internal bool TryRemoveBindingContext()