Xamarin.Forms中RemoveCommand绑定无效问题求助
问题:Xamarin.Forms中RemoveCommand点击无响应,绑定方式存疑
我实现了删除数据库中Note的RemoveCommand,命令能正常显示,但点击后没有任何反应。怀疑是绑定方式的问题,试过多种把RefreshCommand绑定到MenuItem的方法,要么刷新时崩溃,要么删不掉笔记。以下是我的代码:
MyNotePage.xaml
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:model="clr-namespace:MyApp.Models" xmlns:mvvm="clr-namespace:MvvmHelpers;assembly=MvvmHelpers" xmlns:viewmodels="clr-namespace:MyApp.ViewModels" xmlns:xct="http://xamarin.com/schemas/2020/toolkit" x:Class="MyApp.MyNotePage" x:DataType="viewmodels:MyNoteViewModel" BackgroundColor="White"> <ContentPage.BindingContext> <viewmodels:MyNoteViewModel/> </ContentPage.BindingContext> <ContentPage.Resources> <ResourceDictionary> <xct:ItemSelectedEventArgsConverter x:Key="ItemSelectedEventArgsConverter"/> </ResourceDictionary> </ContentPage.Resources> <ContentPage.ToolbarItems> <ToolbarItem Text="Add" Command="{Binding AddCommand}"/> </ContentPage.ToolbarItems> <ListView BackgroundColor="Transparent" CachingStrategy="RecycleElement" HasUnevenRows="True" IsPullToRefreshEnabled="True" IsRefreshing="{Binding IsBusy, Mode=OneWay}" ItemsSource="{Binding Note}" RefreshCommand="{Binding RefreshCommand}" RefreshControlColor="DarkViolet" SelectionMode="None" SeparatorVisibility="None"> <ListView.ItemTemplate> <DataTemplate x:DataType="model:Note"> <ViewCell> <ViewCell.ContextActions> <MenuItem x:DataType="viewmodels:MyNoteViewModel" Command="{Binding Source={RelativeSource AncestorType={x:Type viewmodels:MyNoteViewModel}}, Path=RemoveCommand}" CommandParameter="{Binding}" IsDestructive="True" Text="Delete"/> </ViewCell.ContextActions> <Grid Padding="10"> <Frame CornerRadius="20" HasShadow="True"> <StackLayout Orientation="Horizontal"> <StackLayout VerticalOptions="Center"> <Label FontSize="Large" Text="{Binding Name}" VerticalOptions="Center"/> <Label FontSize="Small" Text="{Binding Id}" VerticalOptions="Center"/> </StackLayout> </StackLayout> </Frame> </Grid> </ViewCell> </DataTemplate> </ListView.ItemTemplate> </ListView>
NoteService.cs
namespace MyApp.Services { public static class NoteService { static SQLiteAsyncConnection db; static async Task Init() { if (db != null) return; { var databasePath = Path.Combine(FileSystem.AppDataDirectory, "MyData.db"); db = new SQLiteAsyncConnection(databasePath); await db.CreateTableAsync<Note>(); } } public static async Task AddNote(string name) { await Init(); var note = new Note() { Name = name, }; await db.InsertAsync(note); } public static async Task RemoveNote(int id) { await Init(); await db.DeleteAsync<Note>(id); } public static async Task<IEnumerable<Note>> GetNote() { await Init(); var note = await db.Table<Note>().ToListAsync(); return note; } } }
MyNoteViewModel.cs
namespace MyApp.ViewModels { public class MyNoteViewModel : ViewModelBase { public ObservableRangeCollection<Note> Note { get; } public AsyncCommand RefreshCommand { get; } public AsyncCommand AddCommand { get; } public AsyncCommand<Note> RemoveCommand { get; } public MyNoteViewModel() { Note = new ObservableRangeCollection<Note>(); RefreshCommand = new AsyncCommand(Refresh); AddCommand = new AsyncCommand(Add); RemoveCommand = new AsyncCommand<Note>(Remove); } async Task Add() { var name = await App.Current.MainPage.DisplayPromptAsync("Notes", "Enter your notes here"); await NoteService.AddNote(name); await Refresh(); } async Task Remove(Note note) { await NoteService.RemoveNote(note.Id); await Refresh(); } async Task Refresh() { IsBusy = true; await Task.Delay(2000); Note.Clear(); var notes = await NoteService.GetNote(); Note.AddRange(notes); IsBusy = false; } } }
解决方案
你的MenuItem绑定问题出在x:DataType的设置上——在DataTemplate内部,你给MenuItem指定了x:DataType="viewmodels:MyNoteViewModel",这会干扰绑定上下文的解析逻辑,导致RelativeSource无法正确找到页面的ViewModel实例。
修改步骤
- 直接移除MenuItem上的
x:DataType="viewmodels:MyNoteViewModel"属性 - 保留原有的Command绑定和CommandParameter绑定,确保能正确获取ViewModel的RemoveCommand和当前Note实例
修改后的MenuItem代码:
<MenuItem Command="{Binding Source={RelativeSource AncestorType={x:Type viewmodels:MyNoteViewModel}}, Path=RemoveCommand}" CommandParameter="{Binding}" IsDestructive="True" Text="Delete"/>
额外检查点
- 确认
Note模型的Id字段标记了[PrimaryKey, AutoIncrement]特性,否则SQLite的DeleteAsync(id)无法准确定位到要删除的记录 - 确保继承的
ViewModelBase正确实现了INotifyPropertyChanged接口,IsBusy属性变更时能触发属性通知,避免下拉刷新状态异常
内容的提问来源于stack exchange,提问作者PuineaGip
相关产品推荐
相关产品推荐

