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

.NET MAUI MVVM:传递ObservableCollection到新增页并返回新对象

解决方案

1. 直接传递ObservableCollection的问题

Shell导航传参虽支持引用类型,但直接传递ObservableCollection存在明显弊端:

  • 容易引发线程安全问题或生命周期不一致(比如新增页ViewModel长期持有集合引用,导致主页面销毁后内存泄漏);
  • 你的AddNewScrum命令冗余——主ViewModel本身就持有集合实例,无需将其作为命令参数传入。

2. 最优实现:导航返回时传递新增对象

无需传递整个集合,只需在新增页创建完DailyScrum后,将对象返回给主ViewModel再添加到集合:

主ViewModel修改AddNewScrum命令

[RelayCommand]
async Task AddNewScrum()
{
    // 导航到新增页并等待返回结果
    var navigationResult = await Shell.Current.GoToAsync($"{nameof(View.AddScrumPage)}", true);
    
    // 解析返回的新增对象
    if (navigationResult.ContainsKey("NewScrum") && navigationResult["NewScrum"] is DailyScrum newScrum)
    {
        // 直接添加到主集合(ObservableCollection自动通知UI更新)
        YourScrumsCollection.Add(newScrum);
    }
}

新增页ViewModel保存后返回

private DailyScrum _newScrum = new DailyScrum();

// 新增页的保存命令
[RelayCommand]
async Task SaveScrum()
{
    // 先完成_newScrum的属性赋值逻辑
    
    // 返回主页面并传递新增对象
    await Shell.Current.GoToAsync("..", true, new Dictionary<string, object>
    {
        {"NewScrum", _newScrum }
    });
}

3. 跨ViewModel共享集合的方案(复杂场景适用)

如果需要多ViewModel共享集合,推荐用单例数据服务托管集合,避免直接传递引用:

1. 创建共享数据服务

public class ScrumDataService
{
    public ObservableCollection<DailyScrum> Scrums { get; } = new ObservableCollection<DailyScrum>();
}

2. 注册单例服务

在项目的依赖注入配置(如App.xaml.cs)中注册:

builder.Services.AddSingleton<ScrumDataService>();

3. 各ViewModel注入服务

// 主ViewModel构造函数
private readonly ScrumDataService _dataService;
public MainViewModel(ScrumDataService dataService)
{
    _dataService = dataService;
    // 绑定到服务中的集合
    YourScrumsCollection = _dataService.Scrums;
}

// 新增页ViewModel构造函数
private readonly ScrumDataService _dataService;
public AddScrumViewModel(ScrumDataService dataService)
{
    _dataService = dataService;
}

// 新增页保存命令
[RelayCommand]
async Task SaveScrum()
{
    _dataService.Scrums.Add(_newScrum);
    await Shell.Current.GoToAsync("..");
}

这种方式下,所有ViewModel共享同一集合实例,新增操作会自动同步到主页面UI。

4. 临时修复传递集合的方式(不推荐)

如果一定要用传递集合的方式,需修正代码:

  • 主ViewModel命令去掉参数,直接用自身集合:
[RelayCommand]
async Task AddNewScrum()
{
    if (YourScrumsCollection is null)
        return;

    await Shell.Current.GoToAsync($"{nameof(View.AddScrumPage)}", true,
        new Dictionary<string, object>
        {
            {"Scrums", YourScrumsCollection }
        });
}
  • 新增页ViewModel通过QueryProperty接收集合:
[QueryProperty(nameof(Scrums), "Scrums")]
public ObservableCollection<DailyScrum> Scrums { get; set; }

[RelayCommand]
async Task SaveScrum()
{
    Scrums.Add(_newScrum);
    await Shell.Current.GoToAsync("..");
}

此方式易引发内存泄漏和线程问题,不建议生产环境使用。

内容的提问来源于stack exchange,提问作者Lilly

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 13:45:26