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

详情页删除数据后,如何更新父页面CollectionView?

解决CollectionView删除后父页面刷新的高效方案

针对你遇到的问题,这里提供几种高效且低耦合的实现方式,无需传递整个列表:


方案一:使用弱引用消息传递(MAUI推荐)

利用MAUI的WeakReferenceMessenger(Xamarin可使用MessagingCenter)实现跨ViewModel的事件通知,只传递被删除项的ID,避免内存泄漏。

步骤1:定义消息类

public class ItemDeletedMessage
{
    public int ItemId { get; }
    public ItemDeletedMessage(int itemId) => ItemId = itemId;
}

步骤2:父页面ViewModel注册消息监听

修改TestViewModel,在构造函数中注册消息,并处理移除逻辑:

using Microsoft.Maui.Controls.Messaging;

public class TestViewModel : BaseViewModel, IDisposable
{
    public ObservableCollection<TestItem> TestItems { get; set; }
    
    public TestViewModel()
    {
        TestItems = new ObservableCollection<TestItem>
        {
            new TestItem { Id = 1, Title = "Test Item 1" },
            new TestItem { Id = 2, Title = "Test Item 2" },
            new TestItem { Id = 3, Title = "Test Item 3" }
        };

        // 注册消息监听
        WeakReferenceMessenger.Default.Register<ItemDeletedMessage>(this, (recipient, message) =>
        {
            var targetItem = TestItems.FirstOrDefault(item => item.Id == message.ItemId);
            if (targetItem != null)
            {
                TestItems.Remove(targetItem);
            }
        });
    }

    [RelayCommand]
    private async Task OnItemSelected(TestItem selectedItem)
    {
        await Shell.Current.Navigation.PushAsync(new DetailsPage(selectedItem));
    }

    // 销毁时取消注册,避免内存泄漏
    public void Dispose()
    {
        WeakReferenceMessenger.Default.Unregister<ItemDeletedMessage>(this);
    }
}

步骤3:详情页ViewModel发送删除通知

修改DetailsPageModel的删除方法,删除数据后发送消息:

public class DetailsPageModel : BaseViewModel
{
    private readonly TestItem _item;
    private readonly ITestRepository _repository; // 假设你的仓储接口

    public DetailsPageModel(TestItem item, ITestRepository repository)
    {
        _item = item;
        _repository = repository;
    }

    [RelayCommand]
    private async void Delete()
    {
        await _repository.Delete(_item);
        // 发送删除消息
        WeakReferenceMessenger.Default.Send(new ItemDeletedMessage(_item.Id));
        await Shell.Current.Navigation.PopAsync();
    }
}

方案二:通过导航返回传递结果

直接在详情页设置返回标识,父页面在返回后读取并更新列表,无需额外依赖,适合简单页面场景。

步骤1:修改详情页,添加返回属性

public partial class DetailsPage : ContentPage
{
    public int? DeletedItemId { get; private set; }

    public DetailsPage(TestItem item)
    {
        InitializeComponent();
        BindingContext = new DetailsPageModel(item, App.Repository); // 假设仓储实例
    }

    // 给ViewModel提供设置属性的方法
    public void SetDeletedItemId(int id) => DeletedItemId = id;
}

步骤2:详情页ViewModel更新返回属性

public class DetailsPageModel : BaseViewModel
{
    private readonly TestItem _item;
    private readonly ITestRepository _repository;
    private readonly DetailsPage _page;

    public DetailsPageModel(TestItem item, ITestRepository repository, DetailsPage page)
    {
        _item = item;
        _repository = repository;
        _page = page;
    }

    [RelayCommand]
    private async void Delete()
    {
        await _repository.Delete(_item);
        _page.SetDeletedItemId(_item.Id);
        await Shell.Current.Navigation.PopAsync();
    }
}

步骤3:父页面ViewModel处理返回结果

[RelayCommand]
private async Task OnItemSelected(TestItem selectedItem)
{
    var detailsPage = new DetailsPage(selectedItem);
    await Shell.Current.Navigation.PushAsync(detailsPage);
    
    // 页面返回后检查是否有删除操作
    if (detailsPage.DeletedItemId.HasValue)
    {
        var targetItem = TestItems.FirstOrDefault(item => item.Id == detailsPage.DeletedItemId.Value);
        if (targetItem != null)
        {
            TestItems.Remove(targetItem);
        }
    }
}

方案三:共享数据更新服务(复杂场景)

通过依赖注入创建单例服务,让父ViewModel订阅服务事件,详情页删除后触发事件,适合多页面需要监听数据变化的场景。

步骤1:创建数据更新服务

public interface IDataUpdateService
{
    event EventHandler<int> ItemDeleted;
    void NotifyItemDeleted(int itemId);
}

public class DataUpdateService : IDataUpdateService
{
    public event EventHandler<int> ItemDeleted;

    public void NotifyItemDeleted(int itemId)
    {
        ItemDeleted?.Invoke(this, itemId);
    }
}

步骤2:注册服务(MAUI Program.cs)

builder.Services.AddSingleton<IDataUpdateService, DataUpdateService>();

步骤3:父ViewModel订阅事件

public class TestViewModel : BaseViewModel, IDisposable
{
    public ObservableCollection<TestItem> TestItems { get; set; }
    private readonly IDataUpdateService _updateService;

    public TestViewModel(IDataUpdateService updateService)
    {
        _updateService = updateService;
        _updateService.ItemDeleted += OnItemDeleted;

        TestItems = new ObservableCollection<TestItem>
        {
            new TestItem { Id = 1, Title = "Test Item 1" },
            new TestItem { Id = 2, Title = "Test Item 2" },
            new TestItem { Id = 3, Title = "Test Item 3" }
        };
    }

    private void OnItemDeleted(object sender, int itemId)
    {
        var targetItem = TestItems.FirstOrDefault(item => item.Id == itemId);
        if (targetItem != null)
        {
            TestItems.Remove(targetItem);
        }
    }

    [RelayCommand]
    private async Task OnItemSelected(TestItem selectedItem)
    {
        await Shell.Current.Navigation.PushAsync(new DetailsPage(selectedItem));
    }

    public void Dispose()
    {
        _updateService.ItemDeleted -= OnItemDeleted;
    }
}

步骤4:详情页ViewModel触发事件

public class DetailsPageModel : BaseViewModel
{
    private readonly TestItem _item;
    private readonly ITestRepository _repository;
    private readonly IDataUpdateService _updateService;

    public DetailsPageModel(TestItem item, ITestRepository repository, IDataUpdateService updateService)
    {
        _item = item;
        _repository = repository;
        _updateService = updateService;
    }

    [RelayCommand]
    private async void Delete()
    {
        await _repository.Delete(_item);
        _updateService.NotifyItemDeleted(_item.Id);
        await Shell.Current.Navigation.PopAsync();
    }
}

注意事项

  1. 原代码中TestViewModel的OnItemSelected方法应为async Task而非async void,避免异步操作异常无法捕获。
  2. DetailsPageModel的构造函数参数原代码写错为TestViewModel,需修正为TestItem。

内容的提问来源于stack exchange,提问作者Zoltán

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 02:29:53