2013-08-23 222 views
2

在我的第一個視圖模型(重命名爲MainViewModel)中,我有一個ActionViewModel列表。 在我的xaml我有一個列表框綁定到列表,在列表框中,我有一個模板綁定到來自ActionViewModel的屬性。如何在更新子視圖模型時更新父視圖模型

到目前爲止這麼好,一切正常。 當選擇其中一個列表項時,我導航到一個ActionViewModel並將其ID傳遞給它。 ActionViewModel從內存中的靜態列表中檢索信息,從該列表中MainViewModel還檢索信息以創建actionviewmodels列表。

到目前爲止仍然非常好,我可以編輯屬性,所有的綁定工作正常,我很高興。 通過單擊保存按鈕收集信息並將其存儲在靜態列表中。 當我點擊後退按鈕時,我會回到列表中,但不幸的是,顯示的值仍然相同,有沒有辦法發送命令來重新加載列表中的項目?傳遞一個完整的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); 
} 

回答

2

我能想到的3種方式可以讓你做到這一點。

  1. ActionService會發出某種通知時,數據的變化。一個簡單的方法就是使用MvvmCross Messenger插件。這是CollectionService.cs的CollectABull服務工作中的mvvmcross視頻的N + 1天路(更多信息觀看http://mvvmcross.wordpress.com N = 13)

    這是我通常使用的方法。它具有較低的開銷,使用WeakReference s(所以不會泄漏內存),它很容易擴展(任何對象都可以監聽變化),並且它鼓勵ViewModel和Model對象的鬆耦合

  2. 您可以實現一些類型爲列表ViewModel上的Refresh API,並可從相應的查看事件(例如ViewDidAppearOnNavigatedToOnResume)調用此API。

    我通常不會使用這種方法來刷新已知數據,但我已經使用它來啓用/禁用資源密集型對象 - 例如,定時器

    對於某些形狀的模型數據(尤其是其變化頻率),我可以想象這種方法可能比信使方法更有效。

  3. 您可以將INotifyPropertyChangedINotifyCollectionChanged的使用擴展回您的模型圖層。

    我已經做了幾次,它對我很好。

    如果您確實選擇了此方法,請注意確保所有視圖都使用WeakReference訂閱來訂閱更改事件,例如MvvmCross綁定中使用的訂閱 - 請參閱WeakSubscription。如果你沒有這樣做,那麼模型可能會導致視圖在內存中保留,即使在UI已經移除它們之後。

+0

第一個解決方案對我來說是最好的解決辦法,看着N = 12和N = YouTube上的13個教程這只是一個執行消息的行動事之後,它的工作就像一個魅力。 – TwanWV