Пример #1
0
        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");
            }
        }
Пример #2
0
        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;
        }
Пример #3
0
        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;
            }
        }