代码之家  ›  专栏  ›  技术社区  ›  Mark Cooper

TreeView MVVM ObservableCollection更新

  •  1
  • Mark Cooper  · 技术社区  · 15 年前

    我有一个树视图,它绑定到许多嵌套的可观察集合。TreeView的每个级别都显示子项中所有小时的总和。例如:

    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 属性和可观察的集合 Teams 在里面 Departments Individuals 在里面 团队 .

    谢谢,
    作记号

    2 回复  |  直到 15 年前
        1
  •  4
  •   Tim Cooper    13 年前

    每个部门的小时数取决于其团队的总小时数。每个小组的时间取决于其个人时间的总和。因此,每个团队都应该听取其个人的 Hours 财产。当检测到时,它应该上升 OnPropertyChanged 为了自己 小时 财产。同样,每个 Department 应该听取其团队的任何更改 小时 财产。当检测到时,它应该上升 OnProperty已更改 为了自己 小时 财产。

    最终结果是,改变任何个人(或团队)的工作时间都会反映在家长中。

    通过重构可以大大改进的psedo代码,但给出了答案的本质:

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

    请注意,如果性能成为一个问题,您可以让集合本身维护小时总数。这样,无论何时只要孩子 小时 属性更改,因为它被告知旧值和新值。因此,它知道应用于聚合的区别。

        2
  •  1
  •   Tim Cooper    13 年前

    我很抱歉,您必须在每个人的父级(“团队”)的父级ObservableCollection容器上明确调用通知。

    然后,从单个父级,为“大父级”(“部门”)设置通知事件。

    Team.OnPropertyChanged("Individuals")