private void OnItemMoved(object sender, ItemMovedEventArgs e) { BeginUpdate(); var stateTracker = new ListBoxStateTracker(this); stateTracker.ApplyChange(ref e); stateTracker.Restore(this); EndUpdate(); // UNDONE: Do some ScrollWindowEx and ValidateRect optimizations here to avoid redrawing // the whole tree. Make sure the TopIndex doesn't change and that there aren't pending redraws // in optimized regions. This should be done along with the OnToggleExpansion optimizations }
// Apply the index change to the selection array and other fields. internal void ApplyChange(ref ItemMovedEventArgs e) { if (e.UpdateTrailingColumns ? restoreColumn < e.Column : restoreColumn != e.Column) { // Nothing to do return; } // The required changes are broken into two adjacent ranges. One range shifts by +/-e.ItemCount, // and the other shifts by e.ToRow-e.FromRow. For an item moving up, the first range is // on top with a positive shift. For an item moving down, the first range is on the bottom // with a negative shift. int rangeTop; // The first item in the top range int rangeMiddle; // The first item in the bottom range int rangeBottom; // The first item not in either range int topShift; // The shift for the top range int bottomShift; // The shift for the bottom range var fromRow = e.FromRow; var toRow = e.ToRow; var itemCount = e.ItemCount; if (fromRow > toRow) { // Item is moving up rangeTop = toRow; rangeMiddle = fromRow; rangeBottom = fromRow + itemCount; topShift = itemCount; bottomShift = toRow - fromRow; } else { // Item is moving down rangeTop = fromRow; rangeMiddle = fromRow + itemCount; rangeBottom = toRow + 1; topShift = toRow - fromRow; bottomShift = -itemCount; } if (restoreSelection != null) { var upper = restoreSelection.GetUpperBound(0) + 1; int testIndex; for (var i = 0; i < upper; ++i) { testIndex = restoreSelection[i]; if (testIndex >= rangeTop) { if (testIndex < rangeMiddle) { restoreSelection[i] = testIndex + topShift; } else if (testIndex < rangeBottom) { restoreSelection[i] = testIndex + bottomShift; } } } } if (restoreTop >= rangeTop) { if (restoreTop < rangeMiddle) { restoreTop += topShift; } else if (restoreTop < rangeBottom) { restoreTop += bottomShift; } } if (restoreCaret >= rangeTop) { if (restoreCaret < rangeMiddle) { restoreCaret += topShift; } else if (restoreCaret < rangeBottom) { restoreCaret += bottomShift; } } if (restoreAnchorIndex >= rangeTop) { if (restoreAnchorIndex < rangeMiddle) { restoreAnchorIndex += topShift; } else if (restoreAnchorIndex < rangeBottom) { restoreAnchorIndex += bottomShift; } } }