2010-01-16 3 views
1

У меня есть дерево, которое привязывается к большому количеству вложенных ObservableCollections. Каждый уровень дерева показывает суммарную сумму всех часов в дочерних элементах. Например:Treeview MVVM ObservableCollection Updates

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" 

Когда я изменить мой Individual.Hours в моем классе ViewModel я хочу, чтобы обновить hours значения в обоих моей команды и отделы тоже.

Я уже использую NotificationProperties для всех моих Hours свойств и ObservableCollections для Teams в Departments и Individuals в Teams.

Спасибо,
Марк

ответ

4

Часы каждого отдела зависят от совокупности часов его команды. Часы каждой команды зависят от совокупности часов своего человека. Таким образом, каждая команда должна прислушиваться к изменениям в свойстве своего Hours. При обнаружении, он должен поднять OnPropertyChanged за свою собственную собственность Hours. Аналогично, каждый Department должен слушать изменения в свойстве Hours своей команды. При обнаружении, он должен поднять OnPropertyChanged за свою собственную собственность Hours.

Конечным результатом является то, что изменение количества часов (или команды) каждого человека отражается в родительском.

Pseduo код, который может быть значительно улучшен с рефакторингом, но дает суть ответа:

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!) 
} 

Обратите внимание, что если производительность становится проблемой вы можете иметь коллекцию сами поддерживать час всего. Таким образом, он может делать простое добавление всякий раз, когда изменяется свойство дочернего пользователя Hours, поскольку ему сообщается старое значение и новое значение. Таким образом, он знает разницу применительно к совокупности.

1

Я напуган, вам придется вызвать в явной форме уведомление о родительском ObservableCollection контейнера для родителей каждого человека («Team»).

Затем от отдельного родителя установите событие уведомления для великого родителя («Департамент»).

Team.OnPropertyChanged("Individuals") 
+0

Спасибо, я думал, что это так. –