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

MAUI中子页面更新数据后如何刷新父页面的ObservableCollection?

MAUI MVVM 创建目标后更新父页面集合的解决方案

问题背景

你有一个带标签页的MAUI应用,导航流程为:DashboardMainPage -> GoalsPage -> CreateGoalPage。在CreateGoalPage完成新目标的本地数据库保存后,需要更新DashboardMainPage和GoalsPage中的目标集合,同时有两个疑问:

  1. 是否应该用弱引用直接操作父ViewModel?
  2. 能否通过BaseViewModel共享ObservableCollection来实现更新?

问题解答

1. 不建议使用弱引用

弱引用直接操作父ViewModel的方式违反MVVM的关注点分离原则:

  • ViewModel之间产生直接依赖,代码耦合度高,后续维护和扩展困难
  • 页面销毁时容易引发内存泄漏或空引用问题,排查成本高
  • 不符合ViewModel独立职责的设计理念,每个ViewModel应只关注自身业务逻辑

2. 不建议在BaseViewModel中共享ObservableCollection

这种方案存在明显缺陷:

  • 不同页面的集合有不同的过滤/分组逻辑:DashboardMainPage只展示未完成目标,GoalsPage分「进行中」和「已完成」两个集合,共享单一集合会导致过滤逻辑混乱,无法满足不同页面的展示需求
  • BaseViewModel是所有ViewModel的通用基类,放入业务相关集合会污染基类,违反单一职责原则
  • 后续新增其他页面需要不同的目标集合展示时,该方案会变得难以维护

推荐解决方案

方案一:利用页面OnAppearing重新加载数据

调整ViewModel的初始化逻辑,去掉IsInitialized的判断(或根据导航场景判断是否刷新),让页面每次显示时重新从数据库加载最新数据:

修改DashboardMainViewModel的InitializeAsync方法

internal async Task InitializeAsync()
{
    // 去掉IsInitialized判断,每次页面出现都重新加载
    await LoadDataAsync();
}

修改GoalsViewModel的InitializeAsync方法

internal async Task InitializeAsync()
{
    await LoadDataAsync();
}

然后在对应的Page的OnAppearing方法中调用InitializeAsync:

protected override async void OnAppearing()
{
    base.OnAppearing();
    if (BindingContext is DashboardMainViewModel vm)
    {
        await vm.InitializeAsync();
    }
}

优点:实现简单,无需额外依赖;缺点:数据量大时会有性能开销,每次都要查询数据库


方案二:使用消息发布订阅(推荐)

利用MVVM Toolkit的WeakReferenceMessenger实现解耦的消息通知,CreateGoalViewModel保存成功后发布消息,其他ViewModel订阅消息并更新自身集合:

1. 定义消息类

public class GoalSavedMessage
{
    public Goal SavedGoal { get; set; }
}

2. 在CreateGoalViewModel中发布消息

[RelayCommand]
private async Task Save()
{
    var savedGoal = await _unitOfWork.Goal.SaveAsync(Goal);
    if (savedGoal is not null)
    {
        // 发布目标保存成功的消息
        WeakReferenceMessenger.Default.Send(new GoalSavedMessage { SavedGoal = savedGoal });
        await NavigationService.GoBackAsync();
    }
}

3. 在DashboardMainViewModel中订阅消息

public DashboardMainViewModel(IUnitOfWork unitOfWork, INavigationService navigationService) : base(navigationService)
{
    _unitOfWork = unitOfWork;
    // 订阅目标保存消息,更新未完成目标集合
    WeakReferenceMessenger.Default.Register<GoalSavedMessage>(this, (recipient, message) =>
    {
        if (!message.SavedGoal.Completed)
        {
            Goals.Add(message.SavedGoal);
        }
    });
}

4. 在GoalsViewModel中订阅消息

public GoalsViewModel(IUnitOfWork unitOfWork, INavigationService navigationService) : base(navigationService)
{
    _unitOfWork = unitOfWork;
    // 订阅目标保存消息,更新对应集合
    WeakReferenceMessenger.Default.Register<GoalSavedMessage>(this, (recipient, message) =>
    {
        if (!message.SavedGoal.IsCompleted)
        {
            OnGoingGoals.Add(message.SavedGoal);
        }
        else
        {
            CompletedGoals.Add(message.SavedGoal);
            // 保持已完成目标按日期降序排列
            CompletedGoals.Sort((a, b) => b.Completed.Date.CompareTo(a.Completed.Date));
        }
    });
}

优点:完全解耦ViewModel,符合MVVM设计原则;性能更优,无需重复查询数据库;扩展性强,后续新增页面只需订阅消息即可


内容的提问来源于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.20 12:13:11