.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
相关产品推荐
相关产品推荐

