2010-01-26 17 views
9

J'utilise le kit de données wpf toolagrid pour afficher une collection observable de AccountViewModels. Lorsque je supprime un compte de la grille, je veux qu'il soit retiré de la collection ObservableCollection - pour donner un retour visuel à l'utilisateur, mais je veux que la liste sous-jacente des modèles Account reste la même, juste avec un 'IsDeleted 'drapeau défini sur le modèle de compte.Comment conserver les collections de viewmodels et de modèles en synchronisation

Ensuite, chaque fois que les modifications sont validées, mon service sait quels comptes ajouter/mettre à jour ou supprimer dans la base de données.

Im abonnée à l'événement CollectionChanged:

AccountViewModels.CollectionChanged += AccountsChanged; 

, puis définir le modèle de viewmodels isDeleted drapeau true lorsque quelque chose est supprimé:

private void AccountsChanged(object sender, NotifyCollectionChangedEventArgs e) 
    { 
     if (e.NewItems != null) 
     { 
      foreach (AccountViewModel model in e.NewItems) 
      { 
       model.PropertyChanged += accountPropertyChanged; 
       model.Account.IsNew = true; 
      } 
     } 
     if (e.OldItems != null) 
     { 

      foreach (AccountViewModel model in e.OldItems) 
      { 
       model.PropertyChanged -= accountPropertyChanged; 
       model.Account.IsDeleted = true; 
      } 
     } 
    } 

mais évidemment cela, il retire ensuite de l'observable collection. Donc, quand je viens de valider les changements, il n'y aura pas de compte avec l'option IsDeleted. c'est-à-dire qu'ils auront déjà été supprimés.

foreach (AccountViewModel acc in m_ViewModel.AccountViewModels) 
     { 
      WorkItem workItem = null; 
      if(acc.Account.IsNew) 
       workItem = new WorkItem("Saving new account: " + acc.AccountName, "Saving new account to the database",() => Service.AddAccount(acc.Account)); 
      else if (acc.Account.IsDeleted) 
       workItem = new WorkItem("Removing account: " + acc.AccountName, "Setting account inactive in the database",() => Service.RemoveAccount(acc.Account)); 
      else if(acc.Account.IsDirty) 
       workItem = new WorkItem("Updating account: " + acc.AccountName, "Updating account in the database",() => Service.UpdateAccount(acc.Account)); 

      workItems.Add(workItem); 

     } 

Donc, cela veut dire que je dois maintenir deux listes, une liste des modèles de compte et l'autre d'une collection observable de accountviewmodels? Cela semble juste méchant et il doit y avoir une meilleure façon de le faire.

Répondre

3

Je ne pense pas que vous puissiez faire cela mieux avec ObservableCollection, car cette classe contient sa propre liste interne d'objets. Toutefois, si vous implémentez une collection personnalisée qui implémente INotifyCollectionChanged et INotifyPropertyChanged, vous pouvez le laisser envelopper et filtrer votre collection source.

Il pourrait filtrer sur l'indicateur IsDeleted afin que ceux-ci ne soient pas visibles.

Chaque fois qu'un utilisateur supprime un élément, vous pouvez modifier directement le modèle de domaine, en définissant l'indicateur IsDeleted sur true. Cependant, vous aurez toujours besoin d'un mécanisme d'événement pour pouvoir déclencher les événements appropriés, mais avec cette approche, vous n'avez qu'une seule collection d'éléments.

La collection personnalisée serait simplement une projection sur le modèle de domaine, avec des événements ajoutés.

+0

Si je vais dans cette voie, comment puis-je capturer la propriété événement a changé lorsque l'un des domaines dans mon modèle est édité dans la grille. Je ne veux pas vraiment que mon modèle de domaine ait à implémenter INotifyPropertyChanged, c'est quelque chose que mon viewmodel faisait précédemment. – cjroebuck

+0

C'est ce que je voulais dire quand j'ai dit que vous aviez besoin d'un mécanisme d'événement en place. Soit vous pouvez déclencher un événement à partir de votre modèle de domaine (il n'a pas besoin d'être INotifiedPropertyChanged - il peut s'agir d'un événement personnalisé), ou vous devez notifier explicitement la collection Projecting de la modification afin qu'elle puisse déclencher les événements corrects. Une troisième option consiste à faire interroger la collection Projecting pour les changements dans le modèle sous-jacent, mais cette route est lourde de danger ... –