Treeview MVVM ObservableCollection更新

时间:2010-01-16 20:23:02

标签: wpf silverlight-3.0 mvvm observablecollection

我有一个树视图,它绑定了许多嵌套的ObservableCollections。树视图的每个级别显示子项中所有小时的总和。例如:

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"  

当我在ViewModel类中修改Individual.Hours时,我想要更新hours 我的团队和部门也都有价值观。

我已经使用NotificationProperties用于我的所有Hours属性,Teams用于DepartmentsIndividuals Teams的ObservableCollections。

谢谢,
标记

2 个答案:

答案 0 :(得分: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 :(得分:1)

我很害怕你必须明确地在父ObservableCollection容器上为每个人的父母('团队')调用通知。

然后从个别父母那里为祖父母('部门')设置通知事件。

Team.OnPropertyChanged("Individuals")