public void ValidateConsistency() { IList <TOuterSourceItem> outerSource = _outerSourceScalar.getValue(_outerSource, new ObservableCollection <TOuterSourceItem>()) as IList <TOuterSourceItem>; IList <TInnerSourceItem> innerSource = _innerSourceScalar.getValue(_innerSource, new ObservableCollection <TInnerSourceItem>()) as IList <TInnerSourceItem>; int index = 0; // ReSharper disable once PossibleNullReferenceException for (int index1 = 0; index1 < outerSource.Count; index1++) { TOuterSourceItem sourceOuterItem = outerSource[index1]; // ReSharper disable once PossibleNullReferenceException for (int index2 = 0; index2 < innerSource.Count; index2++) { TInnerSourceItem sourceInnerItem = innerSource[index2]; JoinPair <TOuterSourceItem, TInnerSourceItem> joinPair = this[index]; if (!EqualityComparer <TOuterSourceItem> .Default.Equals(joinPair.OuterItem, sourceOuterItem)) { throw new ObservableComputationsException(this, "Consistency violation: Crossing.1"); } if (!EqualityComparer <TInnerSourceItem> .Default.Equals(joinPair.InnerItem, sourceInnerItem)) { throw new ObservableComputationsException(this, "Consistency violation: Crossing.2"); } index++; } } // ReSharper disable once PossibleNullReferenceException if (Count != outerSource.Count * innerSource.Count) { throw new ObservableComputationsException(this, "Consistency violation: Crossing.3"); } }
private void handleInnerSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { checkConsistent(sender, e); _handledEventSender = sender; _handledEventArgs = e; if (_innerSourceIndexerPropertyChangedEventRaised || _lastProcessedInnerSourceChangeMarker != _innerSourceAsObservableCollectionWithChangeMarker.ChangeMarkerField) { _innerSourceIndexerPropertyChangedEventRaised = false; _lastProcessedInnerSourceChangeMarker = !_lastProcessedInnerSourceChangeMarker; _isConsistent = false; int newIndex; int oldIndex; switch (e.Action) { case NotifyCollectionChangedAction.Add: //if (e.NewItems.Count > 1) throw new ObservableComputationsException(this, "Adding of multiple items is not supported"); newIndex = e.NewStartingIndex; TInnerSourceItem sourceInnerItem = _innerSourceAsList[newIndex]; int index1 = newIndex; int outerSourceCount1 = _outerSourceAsList.Count; int innerSourceCount1 = _innerSourceAsList.Count; for (int outerSourceIndex = 0; outerSourceIndex < outerSourceCount1; outerSourceIndex++) { TOuterSourceItem sourceOuterItem = _outerSourceAsList[outerSourceIndex]; JoinPair <TOuterSourceItem, TInnerSourceItem> joinPair = new JoinPair <TOuterSourceItem, TInnerSourceItem>( sourceOuterItem, sourceInnerItem); baseInsertItem(index1, joinPair); index1 = index1 + innerSourceCount1; } break; case NotifyCollectionChangedAction.Remove: //if (e.OldItems.Count > 1) throw new ObservableComputationsException(this, "Removing of multiple items is not supported"); oldIndex = e.OldStartingIndex; int outerSourceCount3 = _outerSourceAsList.Count; int oldInnerSourceCount = _innerSourceAsList.Count + 1; int baseIndex = (outerSourceCount3 - 1) * oldInnerSourceCount; for (int outerSourceIndex = outerSourceCount3 - 1; outerSourceIndex >= 0; outerSourceIndex--) { baseRemoveItem(baseIndex + oldIndex); baseIndex = baseIndex - oldInnerSourceCount; } break; case NotifyCollectionChangedAction.Replace: //if (e.NewItems.Count > 1) throw new ObservableComputationsException(this, "Replacing of multiple items is not supported"); newIndex = e.NewStartingIndex; TInnerSourceItem sourceItem3 = _innerSourceAsList[newIndex]; int index2 = newIndex; int outerSourceCount2 = _outerSourceAsList.Count; int innerSourceCount2 = _innerSourceAsList.Count; for (int outerSourceIndex = 0; outerSourceIndex < outerSourceCount2; outerSourceIndex++) { this[index2].setInnerItem(sourceItem3); index2 = index2 + innerSourceCount2; } break; case NotifyCollectionChangedAction.Move: newIndex = e.NewStartingIndex; oldIndex = e.OldStartingIndex; if (newIndex != oldIndex) { int index = 0; int outerSourceCount = _outerSourceAsList.Count; int innerSourceCount = _innerSourceAsList.Count; for (int outerSourceIndex = 0; outerSourceIndex < outerSourceCount; outerSourceIndex++) { baseMoveItem(index + oldIndex, index + newIndex); index = index + innerSourceCount; } } break; case NotifyCollectionChangedAction.Reset: initializeFromSources(); break; } _isConsistent = true; raiseConsistencyRestored(); } _handledEventSender = null; _handledEventArgs = null; }
private void initializeFromSources() { if (_outerSourceNotifyCollectionChangedEventHandler != null) { _outerSource.CollectionChanged -= _outerSourceWeakNotifyCollectionChangedEventHandler.Handle; _outerSourceNotifyCollectionChangedEventHandler = null; _outerSourceWeakNotifyCollectionChangedEventHandler = null; } if (_innerSourceNotifyCollectionChangedEventHandler != null) { _innerSource.CollectionChanged -= _innerSourceWeakNotifyCollectionChangedEventHandler.Handle; _innerSourceNotifyCollectionChangedEventHandler = null; _innerSourceWeakNotifyCollectionChangedEventHandler = null; } if (_innerSourceAsINotifyPropertyChanged != null) { _innerSourceAsINotifyPropertyChanged.PropertyChanged -= _innerSourceWeakPropertyChangedEventHandler.Handle; _innerSourceAsINotifyPropertyChanged = null; _innerSourcePropertyChangedEventHandler = null; _innerSourceWeakPropertyChangedEventHandler = null; } if (_outerSourceAsINotifyPropertyChanged != null) { _outerSourceAsINotifyPropertyChanged.PropertyChanged -= _outerSourceWeakPropertyChangedEventHandler.Handle; _outerSourceAsINotifyPropertyChanged = null; _outerSourcePropertyChangedEventHandler = null; _outerSourceWeakPropertyChangedEventHandler = null; } if (_outerSource != null || _innerSource != null) { baseClearItems(); } if (_outerSourceScalar != null) { _outerSource = _outerSourceScalar.Value; } _outerSourceAsList = (IList <TOuterSourceItem>)_outerSource; if (_innerSourceScalar != null) { _innerSource = _innerSourceScalar.Value; } _innerSourceAsList = (IList <TInnerSourceItem>)_innerSource; if (_outerSource != null && _innerSource != null) { _outerSourceAsObservableCollectionWithChangeMarker = _outerSourceAsList as ObservableCollectionWithChangeMarker <TOuterSourceItem>; if (_outerSourceAsObservableCollectionWithChangeMarker != null) { _lastProcessedOuterSourceChangeMarker = _outerSourceAsObservableCollectionWithChangeMarker.ChangeMarkerField; } else { _outerSourceAsINotifyPropertyChanged = (INotifyPropertyChanged)_outerSource; _outerSourcePropertyChangedEventHandler = (sender, args) => { if (args.PropertyName == "Item[]") { _outerSourceIndexerPropertyChangedEventRaised = true; // ObservableCollection raises this before CollectionChanged event raising } }; _outerSourceWeakPropertyChangedEventHandler = new WeakPropertyChangedEventHandler(_outerSourcePropertyChangedEventHandler); _outerSourceAsINotifyPropertyChanged.PropertyChanged += _outerSourceWeakPropertyChangedEventHandler.Handle; } _innerSourceAsObservableCollectionWithChangeMarker = _innerSourceAsList as ObservableCollectionWithChangeMarker <TInnerSourceItem>; if (_innerSourceAsObservableCollectionWithChangeMarker != null) { _lastProcessedInnerSourceChangeMarker = _innerSourceAsObservableCollectionWithChangeMarker.ChangeMarkerField; } else { _innerSourceAsINotifyPropertyChanged = (INotifyPropertyChanged)_innerSource; _innerSourcePropertyChangedEventHandler = (sender, args) => { if (args.PropertyName == "Item[]") { _innerSourceIndexerPropertyChangedEventRaised = true; // ObservableCollection raises this before CollectionChanged event raising } }; _innerSourceWeakPropertyChangedEventHandler = new WeakPropertyChangedEventHandler(_innerSourcePropertyChangedEventHandler); _innerSourceAsINotifyPropertyChanged.PropertyChanged += _innerSourceWeakPropertyChangedEventHandler.Handle; } // ReSharper disable once PossibleNullReferenceException int outerSourceCount = _outerSourceAsList.Count; // ReSharper disable once PossibleNullReferenceException int innerSourceCount = _innerSourceAsList.Count; int baseIndex = 0; for (int outerSourceIndex = 0; outerSourceIndex < outerSourceCount; outerSourceIndex++) { TOuterSourceItem sourceOuterItem = _outerSourceAsList[outerSourceIndex]; for (int innerSourceIndex = 0; innerSourceIndex < innerSourceCount; innerSourceIndex++) { TInnerSourceItem sourceInnerItem = _innerSourceAsList[innerSourceIndex]; JoinPair <TOuterSourceItem, TInnerSourceItem> joinPair = new JoinPair <TOuterSourceItem, TInnerSourceItem>( sourceOuterItem, sourceInnerItem); baseInsertItem(baseIndex + innerSourceIndex, joinPair); } baseIndex = baseIndex + innerSourceCount; } _outerSourceNotifyCollectionChangedEventHandler = handleOuterSourceCollectionChanged; _outerSourceWeakNotifyCollectionChangedEventHandler = new WeakNotifyCollectionChangedEventHandler(_outerSourceNotifyCollectionChangedEventHandler); _outerSource.CollectionChanged += _outerSourceWeakNotifyCollectionChangedEventHandler.Handle; _innerSourceNotifyCollectionChangedEventHandler = handleInnerSourceCollectionChanged; _innerSourceWeakNotifyCollectionChangedEventHandler = new WeakNotifyCollectionChangedEventHandler(_innerSourceNotifyCollectionChangedEventHandler); _innerSource.CollectionChanged += _innerSourceWeakNotifyCollectionChangedEventHandler.Handle; } }