使用ObservableCollection CollectionChanged事件的问题

时间:2018-02-04 21:38:11

标签: c# wpf

我有ObservableCollection _cableList个包含CableViewModel类型的对象。 CableViewModel对象具有布尔属性IsInDB,如果另一个属性Type列在另一个集合中,则应设置该属性。我收听PropertyChanged事件以更新IsInDB属性。这按预期工作,但我还需要更新添加到集合中的项目的IsInDB属性。我尝试使用以下代码解决此问题:

public MainViewModel()
{
    _cableList = new ObservableCollection<CableViewModel>();
    _cableList.CollectionChanged += _cableListChanged;
}

private void _cableListChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    if(e.OldItems != null)
    {
        foreach (INotifyPropertyChanged item in e.OldItems)
            item.PropertyChanged -= cablePropertyChanged;
    }
    if(e.NewItems != null)
    {
        foreach (INotifyPropertyChanged item in e.NewItems)
        {

            item.PropertyChanged += cablePropertyChanged;
            // This causes an exception
            MessageBox.Show("Collection changed - new Item");   
            var x = (CableViewModel)item;
            x.IsInDB = IsInCableDB(x.Type);
        }
    }
}

代码导致System.InvalidOperationException表示“An ItemsControl与其对象源不一致”,或者至少是我尝试翻译瑞典语错误消息。

我的代码出了什么问题?还有另一种解决方法吗?

编辑

我没有在原帖中显示完整的代码,因为我认为它与异常无关。但是我错了。

在我的原始帖子中,我没有显示或提及我出于调试目的而显示MessageBox。每次将新对象添加到集合时都会显示。现在编辑上面的代码,以便包含MessageBox.Show行。在此处发布原始邮件后,我从代码中删除了MessageBox,结果异常消失了。 MessageBox导致UI与集合不同步吗? (ObservableCollection绑定到DataGrid

2 个答案:

答案 0 :(得分:0)

在这种情况下,我建议使用ReactiveList并使用observables代替事件 - 这会使许多线程问题消失。

从好的方面来说,你可以这样做:

_cableList.ItemChanged.Where(x => x.PropertyName == "Cable").Select(x => x.Sender).Subscribe(x => {
    //do something with the object
    });

_cableList.ItemsAdded.Subscribe(x => x.IsInDB = IsInCableDB(x.Type);

答案 1 :(得分:0)

呃......我的错。在编写代码时,我添加了消息框来了解正在发生的事情。每次触发CollectionChanged时都会显示一个消息框。当我删除消息框时,异常消失了。消息框是否导致UI与数据不同步?