You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 00:55:32