如何正确将SwipeView项绑定到ViewModel中的命令?
问题:SwipeView删除按钮绑定无响应
尝试将SwipeView的删除项绑定到ViewModel的DeleteBook方法,但点击按钮后无任何反应,已尝试修改绑定路径为DeleteBookCommand,也调整过绑定写法,但问题依旧。
现有代码
XAML代码
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:models="clr-namespace:eBooks.Models" xmlns:effectsView="clr-namespace:Syncfusion.Maui.Core;assembly=Syncfusion.Maui.Core" x:Class="eBooks.Library" xmlns:viewmodel="clr-namespace:eBooks.ViewModel" Title="Bibliotheek"> <ContentPage.BindingContext> <viewmodel:LibraryViewModel /> </ContentPage.BindingContext> <Grid> <Grid.RowDefinitions> <RowDefinition Height="auto"></RowDefinition> <RowDefinition Height="*"></RowDefinition> </Grid.RowDefinitions> <Button x:Name="addBookButton" Grid.Row="0" Background="White" TextColor="Black" Text="Voeg een boek toe" Clicked="AddBookButton_Clicked" Margin="0, 20, 0, 0" HeightRequest="44" WidthRequest="300"> <Button.Shadow> <Shadow Brush="White" Radius="15" Opacity="0.8" /> </Button.Shadow> </Button> <CollectionView ItemsSource="{Binding Books}" Margin="36,20,36,20" Grid.Row="1"> <CollectionView.ItemTemplate> <DataTemplate> <SwipeView Margin="0, 5, 10, 0"> <SwipeView.RightItems> <SwipeItem x:Name="deleteButton" Text="Delete" IconImageSource="delete.png" BackgroundColor="{StaticResource Gray950}" Command="{Binding BindingContext.DeleteBook,Source={RelativeSource AncestorType={x:Type viewmodel:LibraryViewModel}}}" CommandParameter="{Binding Id}" /> </SwipeView.RightItems> <Border StrokeThickness="3"> <Border.Stroke> <LinearGradientBrush EndPoint="0,1"> <GradientStop Color="White" Offset="0.1" /> <GradientStop Color="{StaticResource Gray950}" Offset="1.0" /> </LinearGradientBrush> </Border.Stroke> <effectsView:SfEffectsView ScaleFactor="1.15" LongPressEffects="Highlight"> <Grid HeightRequest="84" BackgroundColor="Black"> <Image Aspect="AspectFill" Source="{Binding ThumbnailSource}" Opacity="0.38"/> <Label FontSize="18" TextColor="White" Text="{Binding Title}" FontAttributes="Bold" Margin="32, 24, 0, 0"/> <ProgressBar WidthRequest="250" Margin="0, 46, 0, 0" ProgressColor="White" Progress="{Binding Progress}"/> </Grid> </effectsView:SfEffectsView> </Border> </SwipeView> </DataTemplate> </CollectionView.ItemTemplate> </CollectionView> </Grid>
ViewModel代码
namespace eBooks.ViewModel { public partial class LibraryViewModel : ObservableObject { readonly BookService bookService = new(); public LibraryViewModel() { using var db = new BooksContext(); db.RemoveRange(db.Books); db.SaveChanges(); BookService.OnBooksChanged += RefreshLibrary; RefreshLibrary(); } public void RefreshLibrary(List<Book> books = null) { using var db = new BooksContext(); Books = new ObservableCollection<Book>(db.Books); } [ObservableProperty] ObservableCollection<Book> _books; [RelayCommand] public void DeleteBook(int id) => bookService.Delete(id); } }
解决方案
1. 修正命令绑定路径
使用CommunityToolkit.Mvvm的[RelayCommand]特性时,会自动生成名为{MethodName}Command的命令属性,因此绑定路径应为DeleteBookCommand而非DeleteBook。同时,RelativeSource建议绑定到ContentPage(而非直接指定ViewModel类型),写法更通用:
修改SwipeItem的Command属性:
Command="{Binding BindingContext.DeleteBookCommand, Source={RelativeSource AncestorType={x:Type ContentPage}}}"
2. 确保删除后刷新UI
当前DeleteBook仅调用了bookService.Delete(id),但未更新ViewModel中的Books集合,导致UI不会自动刷新。需要在DeleteBook中触发集合更新:
修改ViewModel中的DeleteBook方法:
[RelayCommand] public void DeleteBook(int id) { bookService.Delete(id); // 刷新Books集合,同步UI RefreshLibrary(); }
3. 验证命令参数类型
确保Book实体的Id属性是int类型,与DeleteBook方法的参数类型完全匹配,否则命令无法触发。
可选优化:直接移除集合项(减少数据库查询)
如果bookService.Delete会同步数据库,也可以直接从Books集合中移除对应项,避免重新查询整个数据库:
[RelayCommand] public void DeleteBook(int id) { bookService.Delete(id); var bookToRemove = Books.FirstOrDefault(b => b.Id == id); if (bookToRemove != null) { Books.Remove(bookToRemove); } }
内容的提问来源于stack exchange,提问作者Woetroe
相关产品推荐
相关产品推荐

