MAUI Shell导航后视图未更新,MVVM模式下如何解决?
MAUI Shell MVVM模式下添加记录后刷新交易列表的解决方案
你的问题根源在于Shell的Tab页面默认会被缓存,TransactionsViewModel的构造函数只在页面首次加载时执行一次,添加新记录后缓存的集合不会自动更新。下面提供几种符合MVVM规范的解决方案:
方案1:通过页面显示事件触发ViewModel刷新
利用TransactionsPage的Appearing事件,每次页面切换回来时主动刷新数据:
第一步:给ViewModel添加刷新方法
修改TransactionsViewModel,把初始化数据的逻辑抽成独立方法,方便重复调用:
public partial class TransactionsViewModel: ObservableObject { public TransactionsViewModel() { LoadTransactions(); } [ObservableProperty] ObservableCollection<Transaction> transactions; // 新增刷新方法 public void LoadTransactions() { var latestTransactions = App.TransactionRepository.GetAllTransactions(); // 清空现有集合再添加新数据,避免重新创建集合导致绑定失效 Transactions.Clear(); foreach (var trans in latestTransactions) { Transactions.Add(trans); } // 也可以直接替换集合:Transactions = new ObservableCollection<Transaction>(latestTransactions); // 因为用了[ObservableProperty],替换时会自动触发属性变更通知 } }
第二步:在页面中订阅显示事件
修改TransactionsPage,每次页面显示时调用ViewModel的刷新方法:
public partial class TransactionsPage : ContentPage { private readonly TransactionsViewModel _viewModel; public TransactionsPage(TransactionsViewModel vm) { InitializeComponent(); _viewModel = vm; BindingContext = vm; // 订阅页面显示事件 Appearing += OnPageAppearing; } private void OnPageAppearing(object sender, EventArgs e) { _viewModel.LoadTransactions(); } // 取消订阅避免内存泄漏 protected override void OnDisappearing() { base.OnDisappearing(); Appearing -= OnPageAppearing; } }
方案2:用弱引用信使实现跨ViewModel通知刷新
这种方式更符合MVVM的解耦要求,添加新记录后主动通知交易列表ViewModel更新:
第一步:定义消息类
新建一个消息类,用来传递新增交易的信息:
public class TransactionAddedMessage { public Transaction NewTransaction { get; set; } }
第二步:在添加页ViewModel发送消息
假设你的添加页ViewModel是AddNewViewModel,保存后发送消息:
public partial class AddNewViewModel : ObservableObject { [ObservableProperty] Transaction newTransaction; [RelayCommand] void SaveTransaction() { // 保存到仓库 App.TransactionRepository.AddTransaction(NewTransaction); // 发送新增交易的消息 WeakReferenceMessenger.Default.Send(new TransactionAddedMessage { NewTransaction = NewTransaction }); // 如果是通过导航跳转而不是Tab切换,这里可以添加导航代码 // await Shell.Current.GoToAsync(nameof(TransactionsPage)); } }
第三步:在交易列表ViewModel订阅消息
修改TransactionsViewModel,订阅消息并更新集合:
public partial class TransactionsViewModel: ObservableObject { public TransactionsViewModel() { LoadTransactions(); // 订阅新增交易的消息 WeakReferenceMessenger.Default.Register<TransactionAddedMessage>(this, (recipient, message) => { // 直接把新交易加到集合里,不用重新查询所有数据 Transactions.Add(message.NewTransaction); // 如果需要同步其他修改(比如删除、编辑),可以调用LoadTransactions()重新加载全部数据 // LoadTransactions(); }); } [ObservableProperty] ObservableCollection<Transaction> transactions; public void LoadTransactions() { Transactions = new ObservableCollection<Transaction>(App.TransactionRepository.GetAllTransactions()); } // 取消订阅避免内存泄漏 ~TransactionsViewModel() { WeakReferenceMessenger.Default.Unregister<TransactionAddedMessage>(this); } }
方案3:禁用页面缓存(不推荐)
如果不需要缓存交易页面,可以修改Shell的CacheMode,每次切换都重新创建页面和ViewModel:
<TabBar> <Tab Title="Transactions"> <ShellContent ContentTemplate="{DataTemplate views:TransactionsPage}" CacheMode="NotCached" /> </Tab> <Tab Title="Add New"> <ShellContent ContentTemplate="{DataTemplate views:AddNewPage}" /> </Tab> </TabBar>
注意:这种方式会导致每次切换页面都重新初始化,频繁切换会影响性能,仅适合数据量极小的场景。
内容的提问来源于stack exchange,提问作者Pablo Aguirre de Souza
相关产品推荐
相关产品推荐

