简体   繁体   中英

Modifying an ObservableCollection using move()?

I have a question relating to modifying the individual items in an ObservableCollection that is bound to a ListBox in the UI.

The user in the UI can multiselect items and then drop them at a particular index to re-order them.

So, if I have items {0,1,2,3,4,5,6,7,8,9} the user can choose items 2, 5, 7 (in that order) and choose to drop them at index 3, so that the collection now becomes,

{0,1,3, 2, 5, 7 , 4, 8,9}

The way I have it working now, is like this inside of ondrop() method on my control, I do something like:

foreach (Item item in draggedItems)
{
   int oldIndex = collection.IndexOf(item.DataContext as MyItemType);
   int newIndex = toDropIndex;

  if (newIndex == collection.Count)
  {
         newIndex--;
  }

  if (oldIndex != newIndex)
  {
     collection.Move(oldIndex, newIndex);                                     
  }

}

But the problem is, if I drop the items before the index where I start dragging my first item, the order becomes reversed...so the collection becomes,

{0,1,3, 7, 5, 2 , 4, 8,9}

It works fine if I drop after index 3, but if I drop it before 3 then the order becomes reversed.

Now, I can do a simple remove and then insert all items at the index I want to, but "move" for me has the advantage of keeping the selection in the ui (remove basically de-selects the items in the list..)....so I will need to make use of the move method,

what is wrong with my method above and how to fix it? Thanks!

foreach (Item item in draggedItems)
{
    int oldIndex = collection.IndexOf(item.DataContext as MyItemType);
    int newIndex = Math.Min(toDropIndex, (collection.Count - 1));

    if (oldIndex == newIndex)
        continue;

    collection.Move(oldIndex, newIndex);

    if (oldIndex > newIndex)
        toDropIndex++;
}

This should help you out. You need to increase the toDropIndex so you're moving each item in front of the last. Otherwise, you're simply moving 2 into index 3, then 5 into index 3 (pushing 2 to index 4), then 7 into index 3 (pushing 2 to index 5 and 5 to index 4). This will, instead, place 2 at index 3, 5 at index 4, and 7 at index 5. The Math.Min() function will ensure that you'll never be out of range.

I think that when you insert them before, you should use newIndex - 1. Try and see if it works.

LE: actualy, i think it's +1

I would speculate that it is because you are not increasing your 'drop index' per item, so each one in the selection order (2, 5, 7) is being inserted at index '3', which will present them in reverse order.

Add;

newIndex++;

on each iteration of the loop.

Or alternately, enumerate your collection in reverse;

for (int i = draggedItems.Count; i >= 0; i--)
{
    . . . 
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM