如何更新子视图模型时如何更新父视图模型

在我的第一个视图模型(重命名为MainViewModel)中,我有一个ActionViewModel列表。 在我的xaml中,我有一个绑定到列表的列表框,在列表框中我有一个模板,它绑定到ActionViewModel的属性。

到目前为止一切都很好,一切正常。 选择其中一个列表项时,我会导航到ActionViewModel并使用它传递id。 ActionViewModel从内存中的静态列表中检索信息,MainViewModel还从中检索信息以创建actionviewmodel列表。

到目前为止仍然很好,我可以编辑属性,所有绑定工作正常,我很高兴。 通过单击保存按钮,信息将被收集并存储在静态列表中。 当我点击后退按钮时,我会返回列表,但遗憾的是显示的值仍然相同,是否有某种方法可以发送命令重新加载列表中的项目? 传递一个完整的viewmodel作为对新ActionViewModel的引用? 或者某些属性告诉父母’你的列表中的这个视图模型已被更新’?

我确信上面的文字有点令人困惑,所以这里有一些代码来澄清它(希望如此)

MainViewModel.cs

private List _actionViewModels; public List ActionViewModels { get { return _actionViewModels; } set { _actionViewModels = value; RaisePropertyChanged(() => ActionViewModels); } } private Cirrious.MvvmCross.ViewModels.MvxCommand _navigateToAction; public System.Windows.Input.ICommand NavigateToAction { get { _navigateToAction = _navigateToAction ?? new Cirrious.MvvmCross.ViewModels.MvxCommand((action) => NavigateToTheDesiredAction(action)); return _navigateToAction; } } private void NavigateToTheDesiredAction(int action) { ShowViewModel(new { id = action }); } // Get DTOs from server or from cache and fill the list of ActionViewModels public async Task Load() { ActionService actionService = new ActionService(); List actionViewModels = new List(); MyActions = await actionService.GetMyActions(); foreach (ActionDTO action in MyActions) { ActionViewModel actionViewModel = new ActionViewModel(); await actionViewModel.Load(action.id); actionViewModels.Add(actionViewModel); } ActionViewModels = actionViewModels; } 

ActionViewModel.cs

 public int ID { get { return TheAction.id; } set { TheAction.id = value; RaisePropertyChanged(() => ID); } } public string Title { get { return TheAction.Title; } set { TheAction.Title = value; RaisePropertyChanged(() => Title); } } public async Task Load(int actionId) { ActionDTO TheAction = await actionService.GetAction(actionId); this.ID = TheAction.id; this.Title = TheAction.Title; } private Cirrious.MvvmCross.ViewModels.MvxCommand _save; public System.Windows.Input.ICommand Save { get { _save = _save ?? new Cirrious.MvvmCross.ViewModels.MvxCommand(PreSaveModel); return _save; } } private void PreSaveModel() { SaveModel(); } private async Task SaveModel() { ValidationDTO result = await actionService.SaveAction(TheAction); } 

ActionService.cs

 public static List AllActions = new List(); public async Task GetAction(int actionId) { ActionDTO action = AllActions.FirstOrDefault(a => a.id == actionId); if (action == null) { int tempActionId = await LoadAction(actionId); if (tempActionId > 0) return await GetAction(actionId); else return new ActionDTO() { Error = new ValidationDTO(false, "Failed to load the action with id " + actionId, ErrorCode.InvalidActionId) }; } return action; } private async Task LoadAction(int actionId) { ActionDTO action = await webservice.GetAction(actionId); AllActions.Add(action); return action.id; } public async Task SaveAction(ActionDTO action) { List currentList = AllActions; ActionDTO removeActionFromList = currentList.FirstOrDefault(a => a.id == action.id); if (removeActionFromList != null) currentList.Remove(removeActionFromList); currentList.Add(action); AllActions = currentList; return await webservice.SaveAction(action); } 

有三种我能想到的方法可以让你做到这一点。

  1. 当数据发生变化时, ActionService可以发出某种通知。 一种简单的方法是使用MvvmCross Messenger插件。 这是CollectABull服务在mvvmcrossvideo的N + 1天内在CollectionService.cs中的工作方式(有关更多信息,请参阅http://mvvmcross.wordpress.com中的 N = 13)

    这是我通常使用的方法。 它具有低开销,使用WeakReference (因此不泄漏内存),它易于扩展(任何对象都可以监听更改),并且它鼓励ViewModel和Model对象的松散耦合

  2. 您可以在列表ViewModel上实现某种类型的Refresh API,并且可以从适当的View事件(例如ViewDidAppearOnNavigatedToOnResume )调用它。

    我一般不会使用这种方法来刷新已知数据,但我已经用它来启用/禁用资源密集型对象 – 例如定时器

    对于某些形状的模型数据(尤其是它的变化频率),我可以想象这种方法可能比信使方法更有效的场景。

  3. 您可以将INotifyPropertyChangedINotifyCollectionChanged的使用扩展回模型层。

    我做了几次,这对我来说很有效。

    如果您确实选择了这种方法,请注意确保所有视图都使用WeakReference订阅(例如MvvmCross绑定中使用的订阅)订阅更改事件 – 请参阅WeakSubscription 。 如果你没有这样做,那么即使在UI本身删除了它之后,模型也可能导致视图在内存中持久存在。