protected override void UpdateOnMove(NotifyCollectionChangedEventArgs e) { base.UpdateOnMove(e); System.Diagnostics.Debug.Assert(e.NewItems.Count == e.OldItems.Count); var items = e.NewItems. OfType <T>(). Select((item, idx) => new { Item = item, Index = idx }). Where(x => _predicate(x.Item)); var position = new ItemPosition(-1, 1); ItemPosition oldDestinationPosition = position, newDestinationPosition = position; for (int idx = 0; idx < _source.Count; idx++) { if (idx == e.NewStartingIndex) { newDestinationPosition = position; } if (idx == e.OldStartingIndex) { oldDestinationPosition = position; } T item = default(T); if (idx >= e.OldStartingIndex && idx < e.OldStartingIndex + e.OldItems.Count) { item = (T)e.OldItems[idx - e.OldStartingIndex]; } else { int afterChangeIndex = idx; if (afterChangeIndex >= e.OldStartingIndex) { afterChangeIndex = afterChangeIndex - e.OldItems.Count; } if (afterChangeIndex >= e.NewStartingIndex) { afterChangeIndex = afterChangeIndex + e.NewItems.Count; } item = _source[afterChangeIndex]; } if (_predicate(item)) { position = new ItemPosition(position.Index + 1, 0); } else { position = new ItemPosition(position.Index, position.Offset + 1); } } foreach (var moved in items) { this.Move(oldDestinationPosition.GetInsertionIndex() + moved.Index, newDestinationPosition.GetInsertionIndex() + moved.Index); } }