避免在Master-Detail MVVM关系中进行递归通知

时间:2016-05-23 16:01:22

标签: c# wpf mvvm

我在使用c#在MVVM WPF三层主 - 详细信息关系中实现级联复选框状态时有一个关于递归的问题。

假设关系是< DIVISION> - < TEAM> - < PLAYER>。如果我检查< DIVISION>,则所有< TEAM>对象和所有< PLAYER> < DIVISION>中的对象应该检查。如果我检查< TEAM>对象,所有< PLAYER> < TEAM>的对象应该检查< DIVISION>复选框状态应该是部分检查或检查,具体取决于< TEAM>的状态。兄弟姐妹。

为此,我在父级持有的子对象的ObservableCollection中的每个项目上分配一个PropertyChanged事件。然后,每个对象将响应相关子集合中对象的更改。每个复选框都绑定到每个模型上的IsChecked属性。 IsChecked属性由私有_isChecked变量支持。 ViewModel保存对顶级< DIVISION>的可观察集合的引用。对象。

情景:

有两个< DIVISION>具有三个< TEAM>的对象对象。每个团队有三个< PLAYER>对象。没有检查任何对象。

用户更改< TEAM>使用关联的复选框将IsChecked状态从False状态转换为True。

< TEAM>调用setter逻辑。

< TEAM>等级IsChecked setter循环通过< PLAYER>列表设置< PLAYER>等级IsChecked值为提供给setter的值。

第一个< PLAYER> IsChecked值切换为true。 < PLAYER> IsChecked状态已更改并正在广播。

< PLAYER>状态变化由< TEAM>检测到。级别改变听众。 < TEAM> IsChecked状态现在已经过部分检查。 < TEAM> IsChecked状态已更改并正在广播。

< TEAM>通过< DIVISION>检测状态变化。级别改变听众。 < DIVISION>州是部分检查。 < DIVISION> IsChecked状态已更改并正在广播。

第二个< PLAYER> IsChecked值切换为true。 < PLAYER> IsChecked状态已更改并正在广播。

< PLAYER>状态变化由< TEAM>检测到。级别改变听众。 < TEAM> IsChecked状态是部分检查。 < TEAM> IsChecked状态没有改变,也没有广播。

第三个也是最后一个< PLAYER> IsChecked值切换为true。 < PLAYER>国家改变是广播。

< TEAM>检测到状态变化。级别改变听众。 < TEAM>检查IsChecked状态。 < TEAM> IsChecked状态已更改并正在广播。

< TEAM>通过< DIVISION>检测状态变化。级别改变听众。 < DIVISION>州是部分检查。 IsChecked状态没有改变,也没有广播。

< TEAM> setter逻辑完成。 < TEAM>对象广播状态变化。

团队设定者逻辑的完成由< DIVISION>检测到。级别改变听众。 < DIVISION>州是部分检查。 < DIVISION> IsChecked状态没有改变,也没有广播。

这是通常的做法吗?这似乎效率很低,感觉有点笨重。有没有更好的方法来实现这一目标?

示例类如下:

            public class DivisionObject : ObservableObject
            {
                bool? _isSelected = false;

                public bool? IsSelected
                {
                    get
                    {
                        return _isSelected;
                    }

                    set
                    {
                        if (value != _isSelected)
                        {
                            foreach (TeamObject p in TeamCollection)
                            {
                                p.IsSelected = value;
                            }

                            _isSelected = value;

                            RaisePropertyChanged("IsSelected");
                        }
                    }
                }

                public string Name { get; set; }
                public int Tier { get; set; }
                public decimal PrizeMoney { get; set; }

                public ObservableCollection<TeamObject> TeamCollection{ get; set; } 

                public DivisionObject()
                {
                    TeamCollection = new ObservableCollection<TeamObject>();
                    TeamCollection.CollectionChanged += TeamCollectionChanged;
                }

                void TeamCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
                {
                    switch (e.Action)
                    {
                        case System.Collections.Specialized.NotifyCollectionChangedAction.Add:
                            foreach (TeamObject t in e.NewItems)
                            {
                                t.PropertyChanged += t_PropertyChanged;
                            }
                            break;
                        case System.Collections.Specialized.NotifyCollectionChangedAction.Remove:
                            foreach (TeamObject t in e.NewItems)
                            {
                                t.PropertyChanged -= t_PropertyChanged;
                            }
                            break;
                    }
                }

                void t_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
                {
                    bool? isSelected = _isSelected;

                    if (e.PropertyName == "IsSelected")
                    {
                        int selectedCount = TeamCollection.ToList().Count(p => p.IsSelected == true);
                        int unselectedCount = TeamCollection.ToList().Count(p => p.IsSelected == false && p.IsSelected != null);

                        if (selectedCount == TeamCollection.Count())
                        {
                            isSelected = true;
                        }
                        else
                        {
                            if (unselectedCount == TeamCollection.Count())
                            {
                                isSelected = false;
                            }
                            else
                            {
                                isSelected = null;
                            }
                        }

                        if (isSelected != _isSelected)
                        {
                            _isSelected = isSelected;
                            RaisePropertyChanged("IsSelected");
                        }
                    }            
                }
            }

            public class TeamObject : ObservableObject
            {
                bool? _isSelected = false;

                public bool? IsSelected 
                {
                    get { return _isSelected; }
                    set
                    {
                        if (value != _isSelected)
                        {                   
                            foreach (PlayerObject a in PlayerCollection)
                            {
                                a.IsSelected = value;
                            }

                            _isSelected = value;

                            RaisePropertyChanged("IsSelected");
                        }
                    }
                }

                public string Name { get; set; }
                public string Ground { get; set; }
                public decimal AverageAttendance { get; set; }
                public int YearFormed { get; set; }

                public ObservableCollection<PlayerObject> PlayerCollection { get; set; }

                public TeamObject()
                {
                    PlayerCollection = new ObservableCollection<PlayerObject>();
                    PlayerCollection.CollectionChanged += PlayerCollection_CollectionChanged;
                }

                void PlayerCollection_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
                {
                    switch (e.Action)
                    {
                        case System.Collections.Specialized.NotifyCollectionChangedAction.Add:
                            foreach (PlayerObject p in e.NewItems)
                            {
                                p.PropertyChanged += p_PropertyChanged;
                            }
                            break;
                        case System.Collections.Specialized.NotifyCollectionChangedAction.Remove:
                            foreach (PlayerObject p in e.NewItems)
                            {
                                p.PropertyChanged -= p_PropertyChanged;
                            }
                            break;
                    }
                }

                void p_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
                {
                    bool? isSelected = _isSelected;

                    if (e.PropertyName == "IsSelected")
                    {
                        int selectedCount = PlayerCollection.ToList().Count(p => p.IsSelected == true);
                        int unselectedCount = PlayerCollection.ToList().Count(p => p.IsSelected == false && p.IsSelected != null);

                        if (selectedCount == PlayerCollection.Count())
                        {
                            isSelected = true;
                        }
                        else
                        {
                            if (unselectedCount == PlayerCollection.Count())
                            {
                                isSelected = false;
                            }
                            else
                            {
                                isSelected = null;
                            }
                        }

                        if (isSelected != _isSelected)
                        {
                            _isSelected = isSelected;
                            RaisePropertyChanged("IsSelected");
                        }
                    }  
                }
            }

            public class PlayerObject : ObservableObject
            {
                bool? _isSelected = false;

                public bool? IsSelected
                {
                    get { return _isSelected; }
                    set 
                    { 
                        if (value != _isSelected) 
                        { 
                            _isSelected = value;
                            RaisePropertyChanged("IsSelected"); 
                        }                

                    }
                }

                public string FirstName { get; set; }
                public string LastName { get; set; }
                public string Position { get; set; }

                public PlayerObject()
                {
                    _isSelected = false;
                }
            }

0 个答案:

没有答案