WPF MVVM - 如何订阅绑定到Grid行的模型实例的PropertyChanged?

时间:2016-11-02 18:09:47

标签: wpf mvvm

我的问题与MVVM in WPF - How to alert ViewModel of changes in Model... or should I?ViewModel subscribing to Model's PropertyChanged event for a specific property非常相似。然而,这是有区别的。

背景资讯

我的模型是员工,我感兴趣的属性是DisplayLtdOccupationId。

但在我的ViewModel中,我不只是拥有一个Employee实例。相反,我有一组Employee对象。

 ObservableCollection<Employee> EmployeeCensus

在我的视图中,我有一个绑定到EmployeeCensus的DataGrid。所以我在网格中有Employee行。

问题

我想要的是能够响应DisplayLtdOccupationId值更改的特定Employee行的PropertyChanged。我想在我的ViewModel中使用处理程序方法执行此操作。

在我的处理程序中,我希望刚刚更改的Employee对象位于'sender'变量中。然后我将使用它的DisplayLtdOccupationId,从我在ViewModel的内存中已经拥有的集合中进行查找,并将查找值设置在同一个Employee对象的不同属性中。

更多详情

ViewModel和Employee Model都实现了INotifyPropertyChanged(通过:Microsoft.Practices.Prism.ViewModel.NotificationObject)。

DataGrid将DisplayLtdOccupationId属性显示为内联下拉列表,用户可以在其中选择不同的值。

为什么不在员工模型中,在SetL of DisplayLtdOccupationId中执行此操作?因为我无权访问那里的查找集合。

我不想在视图中使用触发器来启动处理程序。这导致了一个问题,这也是我想要使用ViewModel和Model仅探索解决方案的原因。

我可以添加更多内容,但我正在尝试将问题简明扼要。如果需要更多信息,请告知。

1 个答案:

答案 0 :(得分:1)

像这样的东西。我想你会希望得到一些更聪明,更简洁的东西,但这就是你得到的。 Employee_PropertyChanged处理Employee属性的更改。您还可以为Employee课程提供针对其DisplayLtdOccupationId媒体资源的更改所引发的特定事件。然后您的父视图模型将处理该事件而不是PropertyChanged。无论哪种方式都有效。

public class ViewModel : ViewModelBase
{
    public ViewModel()
    {
        EmployeeCensus = new ObservableCollection<Employee>();
    }

    #region EmployeeCensus Property
    private ObservableCollection<Employee> _employeeCensus = null;
    public ObservableCollection<Employee> EmployeeCensus
    {
        get { return _employeeCensus; }
        //  Protect this so we don't have to handle the case of somebody giving us
        //  a whole new collection of new Employees. 
        protected set
        {
            if (value != _employeeCensus)
            {
                if (_employeeCensus != null)
                {
                    _employeeCensus.CollectionChanged -= _employeeCensus_CollectionChanged;
                }

                _employeeCensus = value;
                OnPropertyChanged(nameof(EmployeeCensus));

                if (_employeeCensus != null)
                {
                    _employeeCensus.CollectionChanged += _employeeCensus_CollectionChanged;
                }
            }
        }
    }

    private void _employeeCensus_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        if (e.OldItems != null)
        {
            foreach (var item in e.OldItems.Cast<Employee>())
            {
                item.PropertyChanged -= Employee_PropertyChanged;
            }
        }
        if (e.NewItems != null)
        {
            foreach (var item in e.NewItems.Cast<Employee>())
            {
                item.PropertyChanged += Employee_PropertyChanged;
            }
        }
    }

    private void Employee_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        switch (e.PropertyName)
        {
            case nameof(Employee.DisplayLtdOccupationId):
                //  Do stuff
                break;
        }
    }
    #endregion EmployeeCensus Property
}