.NET MAUI删除附件后ObservableCollection未实时更新问题求助
解决.NET MAUI中删除附件后即时更新风险档案视图的问题
问题根源
你在AddAttachmentModal中删除附件时,仅更新了数据库和Modal自身的Attachments集合,但打开的CreateAndUpdateRiskProfileView对应的ViewModel没有收到附件被删除的通知,其内存中的Attachments ObservableCollection并未同步移除该附件,因此视图不会自动刷新,直到重启应用重新加载数据。
解决方案:使用MVVM Toolkit的Messenger实现跨ViewModel通信
利用CommunityToolkit.Mvvm中的IMessenger可以轻松实现ViewModel之间的消息传递,在附件被删除时通知风险档案ViewModel更新集合。
步骤1:定义删除附件的消息类
在项目中添加一个消息类,用于传递被删除的附件对象:
using CommunityToolkit.Mvvm.Messaging.Messages; using SiRiAs.Lib.Models; namespace SiRiAs.Lib.Messages { public class AttachmentDeletedMessage : ValueChangedMessage<Attachment> { public AttachmentDeletedMessage(Attachment value) : base(value) { } } }
步骤2:在CreateAndUpdateRiskProfileViewModel中注册消息监听
修改CreateAndUpdateRiskProfileViewModel,注入IMessenger并注册消息处理:
using CommunityToolkit.Mvvm.Messaging; // ... 其他using [QueryProperty(nameof(Intent), nameof(Intent))] [QueryProperty(nameof(Model), nameof(Model))] [QueryProperty(nameof(ActivityId), nameof(ActivityId))] public partial class CreateAndUpdateRiskProfileViewModel : ObservableObject, IRecipient<AttachmentDeletedMessage> { private readonly IUnitOfWork _unitOfWork; private readonly IPopupProvider _popupProvider; private readonly IMessenger _messenger; // ... 现有代码 public CreateAndUpdateRiskProfileViewModel(IUnitOfWork unitOfWork, IPopupProvider popupProvider, IMessenger messenger) { _unitOfWork = unitOfWork; _popupProvider = popupProvider; _messenger = messenger; _messenger.Register(this); // 注册消息监听 PopulateRiskCategories(); } // 实现消息处理方法 public void Receive(AttachmentDeletedMessage message) { var deletedAttachment = message.Value; // 检查并移除集合中的对应附件 var existingAttachment = Attachments.FirstOrDefault(a => a.Id == deletedAttachment.Id); if (existingAttachment != null) { Attachments.Remove(existingAttachment); isModelDirty = true; // 同步更新Model中的附件列表 Model.Attachments.Remove(existingAttachment); } } // 视图销毁时注销监听,避免内存泄漏 public void Cleanup() { _messenger.UnregisterAll(this); } }
步骤3:在CreateAndUpdateRiskProfileView中添加清理逻辑
在视图的OnDisappearing方法中调用ViewModel的清理方法:
protected override void OnDisappearing() { base.OnDisappearing(); _viewModel.Cleanup(); }
步骤4:在AddAttachmentModalViewModel中发送删除消息
修改AddAttachmentModalViewModel的ShowDeleteOption方法,删除附件后发送消息:
using CommunityToolkit.Mvvm.Messaging; // ... 其他using public partial class AddAttachmentModalViewModel : ObservableObject { private readonly IUnitOfWork _unitOfWork; private readonly IPopupProvider _popupProvider; private readonly IMessenger _messenger; // ... 现有代码 public AddAttachmentModalViewModel(IUnitOfWork unitOfWork, IPopupProvider popupProvider, IAudioRecorder audioRecorder, IMessenger messenger) { _unitOfWork = unitOfWork; _popupProvider = popupProvider; _audioRecorder = audioRecorder; _messenger = messenger; OnSelectedAttachmentTypeChanged(SelectedAttachmentType); } [RelayCommand] public async void ShowDeleteOption(Attachment attachment) { var result = await _popupProvider.ShowDeleteAttachmentPopup(); if(result.Equals(DeleteDialogResult.Delete)) { var deleteResult = await _popupProvider.ShowDeletePopup(); if(deleteResult.Equals(DeleteDialogResult.Delete)) { _unitOfWork.Attachments.Remove(attachment); await _unitOfWork.Save(); Attachments.Remove(attachment); // 发送附件删除消息 _messenger.Send(new AttachmentDeletedMessage(attachment)); foreach(RiskProfile riskProfile in await _unitOfWork.RiskProfiles.GetAll()) { if(riskProfile.Attachments.Contains(attachment)) { riskProfile.Attachments.Remove(attachment); } } // 保存风险档案的更新 await _unitOfWork.Save(); } } } }
其他可选方案:关闭Modal时刷新附件列表
如果不想用消息传递,也可以在关闭AddAttachmentModal后重新加载附件列表,适合小型应用:
[RelayCommand] public async void AddAttachment() { var selectedAttachment = await _popupProvider.ShowAddAttachmentPopup(); if (selectedAttachment is not null && !AttachmentAlreadyAttached(selectedAttachment)) { Attachments.Add(selectedAttachment); isModelDirty = true; } // 刷新附件列表,同步删除的内容 RefreshAttachments(); } private async void RefreshAttachments() { // 从数据库重新加载当前风险档案的附件 var freshProfile = await _unitOfWork.RiskProfiles.GetById(Model.Id); if (freshProfile != null) { Attachments = new ObservableCollection<Attachment>(freshProfile.Attachments); } }
内容的提问来源于stack exchange,提问作者Leah Fernández
相关产品推荐
相关产品推荐

