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