// move an item and return true if it really moved. // Also translate the indices to "leaf" coordinates internal bool Move(object item, IList list, ref int oldIndex, ref int newIndex) { int oldIndexLocal = -1, newIndexLocal = -1; int localIndex = 0; int n = ProtectedItems.Count; // the input is in "full" coordinates. Find the corresponding local coordinates for (int fullIndex = 0; ; ++fullIndex) { if (fullIndex == oldIndex) { oldIndexLocal = localIndex; if (newIndexLocal >= 0) { break; } ++localIndex; } if (fullIndex == newIndex) { newIndexLocal = localIndex; if (oldIndexLocal >= 0) { --newIndexLocal; break; } ++fullIndex; ++oldIndex; } if (localIndex < n && ItemsControl.EqualsEx(ProtectedItems[localIndex], list[fullIndex])) { ++localIndex; } } // the move may be a no-op w.r.t. this group if (oldIndexLocal == newIndexLocal) { return(false); } // translate to "leaf" coordinates int low, high, lowLeafIndex, delta = 0; if (oldIndexLocal < newIndexLocal) { low = oldIndexLocal + 1; high = newIndexLocal + 1; lowLeafIndex = LeafIndexFromItem(null, oldIndexLocal); } else { low = newIndexLocal; high = oldIndexLocal; lowLeafIndex = LeafIndexFromItem(null, newIndexLocal); } for (int i = low; i < high; ++i) { CollectionViewGroupInternal subgroup = Items[i] as CollectionViewGroupInternal; delta += (subgroup == null) ? 1 : subgroup.ItemCount; } if (oldIndexLocal < newIndexLocal) { oldIndex = lowLeafIndex; newIndex = oldIndex + delta; } else { newIndex = lowLeafIndex; oldIndex = newIndex + delta; } // do the actual move ProtectedItems.Move(oldIndexLocal, newIndexLocal); return(true); }