2010-01-16 5 views
1

J'ai une arborescence qui se lie à beaucoup de ObservableCollections imbriquées. Chaque niveau de l'arborescence affiche une somme agrégée de toutes les heures des éléments enfants. Par exemple:Treeview MVVM ObservableCollection Mises à jour

Department 1, 10hrs 
    ├ Team 10, 5hrs 
    │ ├ Mark, 3hrs 
    │ └ Anthony, 2hrs 
    └ Team 11, 5hrs 
    ├ Jason, 2hrs 
    ├ Gary, 2hrs 
    └ Hadley, 1hrs 
Department 2, 4hrs 
    ├ Team 20, 3hrs 
    │ ├ Tabitha, 0.5hrs 
    │ ├ Linsey, 0.5hrs 
    │ └ Guy, 2hrs 
    └ Team 11, 1hr 
    └ "Hadley, 1hr" 

Quand je modifie mon Individual.Hours dans ma classe ViewModel je veux mettre à jour les hours valeurs tant dans mon équipe et les services aussi.

J'utilise déjà NotificationProperties pour toutes mes propriétés Hours et ObservableCollections pour Teams dans Departments et Individuals dans Teams.

Merci,
Mark

Répondre

4

Les heures de chaque département dépendent de l'ensemble des heures de son équipe. Les heures de chaque équipe dépendent de l'ensemble des heures de son individu. Ainsi, chaque équipe doit être à l'écoute des modifications apportées à la propriété Hours de son individu. Lorsqu'il est détecté, il doit générer OnPropertyChanged pour sa propriété Hours. De même, chaque Department doit être à l'écoute des modifications apportées à la propriété Hours de son équipe. Lorsqu'il est détecté, il doit générer OnPropertyChanged pour sa propriété Hours.

Le résultat final est que la modification des heures d'une personne (ou d'une équipe) est reflétée dans le parent.

Code pseduo qui peut être grandement améliorée avec refactoring, mais donne l'essence de la réponse:

public class Individual : ViewModel 
{ 
    public int Hours 
    { 
     // standard get/set with property change notification 
    } 

} 

public class Team : ViewModel 
{ 
    public Team() 
    { 
     this.individuals = new IndividualCollection(this); 
    } 

    public ICollection<Individual> Individuals 
    { 
     get { return this.individuals; } 
    } 

    public int Hours 
    { 
     get 
     { 
      // return sum of individual's hours (can cache for perf reasons) 
     } 
    } 

    // custom collection isn't strictly required, but makes the code more readable 
    private sealed class IndividualCollection : ObservableCollection<Individual> 
    { 
     private readonly Team team; 

     public IndividualCollection(Team team) 
     { 
      this.team = team; 
     } 

     public override Add(Individual individual) 
     { 
      individual.PropertyChanged += IndividualPropertyChanged; 
     } 

     public override Remove(...) 
     { 
      individual.PropertyChanged -= IndividualPropertyChanged; 
     } 

     private void IndividualPropertyChanged(object sender, PropertyChangedEventArgs e) 
     { 
      if (e.PropertyName == "Hours") 
      { 
       team.OnPropertyChanged("Hours"); 
      } 
     } 
    } 
} 

public class Department : ViewModel 
{ 
    public Department() 
    { 
     this.teams = new TeamCollection(); 
    } 

    public ICollection<Team> Teams 
    { 
     get { return this.teams; } 
    } 

    public int Hours 
    { 
     get 
     { 
      // return sum of team's hours (can cache for perf reasons) 
     } 
    } 

    // TeamCollection very similar to IndividualCollection (think generics!) 
} 

Notez que si la performance devient un problème, vous pouvez avoir la collection elle-même maintenir l'heure totale. De cette façon, il peut faire un ajout simple chaque fois que la propriété Hours d'un enfant change, parce qu'on lui dit l'ancienne valeur et la nouvelle valeur. Ainsi, il connaît la différence à appliquer à l'agrégat.

1

Je suis affraid vous devrez appeler la notification explicity sur le récipient ObservableCollection mère pour le parent de chaque individu ('équipe').

Ensuite, à partir du parent individuel, définissez l'événement de notification pour grand parent ('Département').

Team.OnPropertyChanged("Individuals") 
+0

Merci, je pensais que c'était le cas. –

Questions connexes