简体   繁体   中英

Prolems with ObservableCollection CollectionChanged event

I have an ObservableCollection _cableList containing objects of type CableViewModel . The CableViewModel objects have a boolean property IsInDB that should be set if another property Type is listed i another collection. I listen to the PropertyChanged event in order to update the IsInDB property. This works as intended but I also need to update the IsInDB property for items that are added to the collection. I attempt to solve this with the following code:

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

The code causes an System.InvalidOperationException that says something like "An ItemsControl is inconsistent with its object source" or at least that´s my attempt to translate from the Swedish error message.

What is wrong with my code? Is there a another way to solve the task?

EDIT

I did not show the complete code in my original post as I didn't think it was related to the exception. But I was wrong.

In my original post I did not show or mention that I showed a MessageBox for debugging purposes. It was shown each time a new object was added to the collection. The code above is now edited so that MessageBox.Show line is included. After posting the original message here I removed the MessageBox from the code and as a result the exception disappeared. Did the MessageBox cause the UI to get out of sync with the collection? (The ObservableCollection is bound to a DataGrid )

In that case I would suggest using ReactiveList and use observables instead of events - it makes lots of threading problems go away.

On the plus side, you can then do something like this:

_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);

Ehh... my mistake. When authoring the code I added messageboxes to learn what was going on. Each time the CollectionChanged was triggered a messagebox was shown. When I removed the messageboxes the exceptions disappeared. Did the messageboxes cause the UI get out of sync with the data?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM