Comment mettre à jour le modèle de vue parent lorsque le modèle de vue enfant est mis à jour

Dans mon premier modèle de vue (renommé MainViewModel), j’ai une liste de ActionViewModels. Dans mon xaml, j’ai une liste qui est liée à la liste, dans la liste, j’ai un modèle qui se lie aux propriétés de ActionViewModel.

Jusqu’ici tout va bien et tout fonctionne. Lors de la sélection de l’un des éléments de liste, je navigue vers un ActionViewModel et lui passe l’identifiant. ActionViewModel extrait les informations d’une liste statique en mémoire à partir de laquelle MainViewModel a également extrait les informations pour créer la liste des actionsviewmodels.

Jusqu’ici, tout va bien, je peux éditer les propriétés, toutes les liaisons fonctionnent bien et je suis heureux. En cliquant sur le bouton Sauvegarder, les informations sont rassemblées et stockées dans la liste statique. Lorsque je clique sur le bouton retour, je retourne à la liste, mais malheureusement, les valeurs montrant qu’il y a toujours la même chose, existe-t-il un moyen d’envoyer une commande pour recharger les éléments de la liste? Pour passer un modèle de vue complet en tant que référence à un nouveau ActionViewModel? Ou une propriété qui indique au parent que “ce modèle de vue de votre liste a été mis à jour”?

Je suis sûr que le texte ci-dessus est un peu déroutant, donc voici un code pour le clarifier un peu (espérons-le)

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 ssortingng 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); } 

Je peux penser à cela de trois manières qui vous permettraient de le faire.

  1. ActionService pourrait envoyer une sorte de notification lorsque les données sont ActionService . Une méthode simple consiste à utiliser le plug-in MvvmCross Messenger. C’est ainsi que fonctionne le service CollectABull dans CollectionService.cs dans les N + 1 jours de vidéos mvvmcross (pour plus d’informations, regardez N = 13 dans http://mvvmcross.wordpress.com )

    C’est l’approche que j’utilise généralement. Il a peu de temps système, utilise WeakReference s (il ne fuit donc pas de mémoire), il est facilement extensible (tout object peut écouter les modifications) et encourage un couplage lâche des objects ViewModel et Model.

  2. Vous pouvez implémenter une sorte d’API de Refresh dans la liste ViewModel et l’appeler à partir des événements View appropriés (par exemple, ViewDidAppear , OnNavigatedTo et OnResume ).

    Je n’utilise généralement pas cette approche pour actualiser des données connues, mais je l’ai utilisée pour activer / désactiver des objects gourmands en ressources, par exemple des timers.

    Pour certaines formes de données de modèle (et en particulier la fréquence à laquelle elles changent), je peux alors imaginer des scénarios dans lesquels cette approche pourrait être plus efficace que l’approche par messager.

  3. Vous pouvez étendre l’utilisation d’ INotifyPropertyChanged et d’ INotifyCollectionChanged à votre couche de modèle.

    Je l’ai fait plusieurs fois et cela a bien fonctionné pour moi.

    Si vous choisissez cette approche, veillez à ce que toutes les vues s’abonnent aux événements de modification à l’aide d’abonnements WeakReference tels que ceux utilisés dans la liaison MvvmCross – voir WeakSubscription . Si vous ne le faisiez pas, le modèle pourrait peut-être faire en sorte que les vues restnt en mémoire même après que l’interface utilisateur les a supprimées.