0

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)

J.Thor
  • 61
  • 1
  • 5
  • This sounds like a duplicate of this question: https://stackoverflow.com/questions/22524569/an-itemscontrol-is-inconsistent-with-its-items-source-wpf-listbox and is probably unrelated this specific part of your code. It more like has something to do with where the collection is being changed. – Mike Zboray Feb 04 '18 at 21:47
  • I didn't tell the complete story. The ObservableCollection is bound to a DataGrid. The inner exception tells me that the DataGrid control received a sequence of CollectionChanged events that do not match the current state of the object collection. Does that make any difference? – J.Thor Feb 04 '18 at 22:13

2 Answers2

0

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);
Krzysztof Skowronek
  • 2,796
  • 1
  • 13
  • 29
  • I'm rookie hobby programmer trying to learn C# and WPF. Having to learn yet another package scares me, but I will take it into consideration :) – J.Thor Feb 04 '18 at 22:19
  • this package, alongside ReactiveExtensions, will blow your mind and rocket jump your skill. It's worth your time – Krzysztof Skowronek Feb 05 '18 at 08:51
0

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?

J.Thor
  • 61
  • 1
  • 5
  • you should have edited your question to include more details instead of posting an answer? what messagebox are you asking about? there is none in the question – ASh Feb 05 '18 at 07:03
  • Yes, you a correct - that is what I should have done! I have now edited the original question. – J.Thor Feb 05 '18 at 15:27