使用TouchBehavior时LongPressCommandParameter始终传递相同参数的问题
问题描述
按压或长按操作触发对应方法时,无论调用多少次,始终传递首次选中的元素。例如,选择分类"1"后返回分类页面,后续选择任意分类,按压和长按操作都会传递分类"1"的对象。
相关代码
CategoryViewModel.cs
[ObservableProperty] private ObservableCollection<Category> _categories = new(); [RelayCommand] async Task AddOperation(Category category) { await Shell.Current.GoToAsync(nameof(AddOperationPage), new Dictionary<string, object> { { "choosencategory", category } }); }
Category.xaml
<CollectionView x:Name="collectionView" ItemsSource="{Binding Categories}" ItemsLayout="VerticalGrid, 2" SelectedItem="{Binding SelectedCategory}"> <CollectionView.ItemTemplate> <DataTemplate x:DataType="models:Category"> <Border BackgroundColor="White" StrokeShape="RoundRectangle 40" StrokeThickness="2" Stroke="{StaticResource Primary}" Margin="10"> <Grid ColumnDefinitions="0.3*,0.7*" RowDefinitions="0.5*,0.5*"> <Grid.Behaviors> <toolkit:TouchBehavior Command="{Binding Source={x:Reference collectionView}, Path=BindingContext.AddOperationCommand}" CommandParameter="{Binding .}" LongPressDuration="800" LongPressCommand="{Binding Source={x:Reference collectionView}, Path=BindingContext.ChangeCategoryCommand}" LongPressCommandParameter="{Binding .}"/> </Grid.Behaviors> <Border Grid.Column="0" Grid.Row="0" Grid.RowSpan="2" Grid.ColumnSpan="1" Style="{StaticResource BorderCategory}" Padding="10" StrokeThickness="2" Stroke="Black"> <Image Source="{Binding IconPath}" Margin="10"> <Image.Behaviors> <toolkit:IconTintColorBehavior TintColor="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}"/> </Image.Behaviors> </Image> </Border> <Label Grid.Column="1" Grid.Row="0" Text="{Binding Name}" TextColor="Black" HorizontalOptions="Center"/> <Label Grid.Column="1" Grid.Row="1" Text="{Binding Count}" TextColor="Black" HorizontalOptions="Center"/> </Grid> </Border> </DataTemplate> </CollectionView.ItemTemplate> </CollectionView>
解决方案
1. 重置选中状态
让ViewModel实现INavigatedAware接口,在返回分类页面时清空选中项,避免状态残留:
public class CategoryViewModel : ObservableObject, INavigatedAware { [ObservableProperty] private ObservableCollection<Category> _categories = new(); [ObservableProperty] private Category? _selectedCategory; [RelayCommand] async Task AddOperation(Category category) { await Shell.Current.GoToAsync(nameof(AddOperationPage), new Dictionary<string, object> { { "choosencategory", category } }); } public void OnNavigatedTo(NavigatedToEventArgs args) { SelectedCategory = null; } public void OnNavigatedFrom(NavigatedFromEventArgs args) { SelectedCategory = null; } }
2. 强制命令参数单向绑定
修改TouchBehavior的参数绑定,显式设置Mode=OneWay,确保每次操作获取当前项的最新绑定:
<toolkit:TouchBehavior Command="{Binding Source={x:Reference collectionView}, Path=BindingContext.AddOperationCommand}" CommandParameter="{Binding ., Mode=OneWay}" LongPressDuration="800" LongPressCommand="{Binding Source={x:Reference collectionView}, Path=BindingContext.ChangeCategoryCommand}" LongPressCommandParameter="{Binding ., Mode=OneWay}"/>
3. 检查ViewModel实例生命周期
确认CategoryViewModel不是不必要的单例模式,若为单例需确保每次进入页面时重置状态,避免旧数据残留。
4. 刷新CollectionView绑定(可选)
若上述方法无效,可在页面OnAppearing中重新设置ItemsSource,触发ItemTemplate重建:
public partial class CategoryPage : ContentPage { private CategoryViewModel _viewModel; public CategoryPage(CategoryViewModel viewModel) { InitializeComponent(); _viewModel = viewModel; BindingContext = viewModel; } protected override void OnAppearing() { base.OnAppearing(); collectionView.ItemsSource = null; collectionView.ItemsSource = _viewModel.Categories; } }
内容的提问来源于stack exchange,提问作者user30029575
相关产品推荐
相关产品推荐

