在我的第一个视图模型(重命名为MainViewModel)中,我有一个ActionViewModel列表。 在我的xaml中,我有一个绑定到列表的列表框,在列表框中我有一个模板,它绑定到ActionViewModel的属性。
到目前为止一切都那么好,一切正常。 选择其中一个列表项时,我会导航到ActionViewModel并使用它传递id。 ActionViewModel从内存中的静态列表中检索信息,MainViewModel也从中检索信息以创建actionviewmodel列表。
到目前为止仍然很好,我可以编辑属性,所有绑定都可以正常工作,我很高兴。 通过单击保存按钮,信息将被收集并存储在静态列表中。 当我点击后退按钮时,我会回到列表中,但遗憾的是显示的值仍然相同,是否有某种方法可以发送命令重新加载列表中的项目?传递一个完整的viewmodel作为对新ActionViewModel的引用?或者某些属性告诉父母'你的列表中的这个视图模型已被更新'?
我确信上面的文字有点令人困惑,所以这里有一些代码可以澄清一下(希望如此)
MainViewModel.cs
private List<ActionViewModel> _actionViewModels;
public List<ActionViewModel> ActionViewModels
{
get { return _actionViewModels; }
set { _actionViewModels = value; RaisePropertyChanged(() => ActionViewModels); }
}
private Cirrious.MvvmCross.ViewModels.MvxCommand<int> _navigateToAction;
public System.Windows.Input.ICommand NavigateToAction
{
get
{
_navigateToAction = _navigateToAction ?? new Cirrious.MvvmCross.ViewModels.MvxCommand<int>((action) => NavigateToTheDesiredAction(action));
return _navigateToAction;
}
}
private void NavigateToTheDesiredAction(int action)
{
ShowViewModel<ActionViewModel>(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<ActionViewModel> actionViewModels = new List<ActionViewModel>();
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<ActionDTO> AllActions = new List<ActionDTO>();
public async Task<ActionDTO> 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<int> LoadAction(int actionId)
{
ActionDTO action = await webservice.GetAction(actionId);
AllActions.Add(action);
return action.id;
}
public async Task<ValidationDTO> SaveAction(ActionDTO action)
{
List<ActionDTO> 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);
}
答案 0 :(得分:2)
我有三种方法可以让你这样做。
ActionService
可能会在数据发生变化时发出某种通知。一种简单的方法是使用MvvmCross Messenger插件。这是在mvvmcross视频的N + 1天内CollectABull服务在CollectionService.cs中的工作方式(有关更多信息,请在http://mvvmcross.wordpress.com中观看N = 13)
这是我通常使用的方法。它具有低开销,使用WeakReference
s(因此不会泄漏内存),它易于扩展(任何对象都可以监听更改),并且它鼓励ViewModel和Model对象的松散耦合
您可以在列表ViewModel上实现某种Refresh
API,并且可以从相应的View事件中调用它(例如ViewDidAppear
,OnNavigatedTo
和OnResume
)
我通常不会使用此方法来刷新已知数据,但我已将其用于启用/禁用资源密集型对象 - 例如定时器
对于某些形状的模型数据(尤其是它的变化频率),我可以想象这种方法可能比信使方法更有效。
您可以将INotifyPropertyChanged
和INotifyCollectionChanged
的使用扩展回模型层。
我已经做了几次,这对我来说效果很好。
如果您确实选择了这种方法,请注意确保所有视图都使用WeakReference
订阅订阅更改事件,例如MvvmCross绑定中使用的订阅 - 请参阅WeakSubscription。如果你没有这样做,那么即使在UI本身删除它之后,模型也可能导致视图在内存中持久存在。