I have a ListView (WinForms) in which i want to move items up and down with the click of a button. The items to be moved are the ones who are checked. So if item 2, 6 and 9 are
Try something like this:
foreach (ListViewItem lvi in sourceListView.SelectedItems)
{
if (lvi.Index > 0)
{
int index = lvi.Index - 1;
sourceListView.Items.RemoveAt(lvi.Index);
sourceListView.Items.Insert(index, lvi);
}
}
Basically just removes the item then inserts it above of where it used to be. The ListView automatically handles reshuffling the items down the order after an insert so no worries.
Edit:
The reason the two topmost items swap is that the top item will never move (i.e I haven't implemented a wrap-around
move. The 2nd item, however, is free to move and thus goes to the top of the list.
To resolve this, you can do 1 of 2 things:
- Implement a wrap-around reshuffle (i.e top item goes to the bottom)
- Prevent any movement if the top item is selected (check listview.Items[0].Selected)
As for the re-doing of the text, just do it in the original loop.
Implementation with wraparound:
foreach (ListViewItem lvi in sourceListView.SelectedItems)
{
int index = lvi.Index > 0 ? lvi.Index - 1 : sourceListView.Items.Count - 1;
sourceListView.Items.RemoveAt(lvi.Index);
sourceListView.Items.Insert(index, lvi);
if (index != sourceListView.Items.Count - 1) //not a wraparound:
{
//just swap the indices over.
sourceListView.Items[index + 1].SubItems[1].Text = (index + 1).ToString();
lvi.SubItems[1].Text = index.ToString();
}
else //item wrapped around, have to manually update all items.
{
foreach (ListViewItem lvi2 in sourceListView.Items)
lvi2.SubItems[1].Text = lvi2.Index.ToString();
}
}
Static helper implementation, no wrap-around:
private enum MoveDirection { Up = -1, Down = 1 };
private static void MoveListViewItems(ListView sender, MoveDirection direction)
{
int dir = (int)direction;
int opp = dir * -1;
bool valid = sender.SelectedItems.Count > 0 &&
((direction == MoveDirection.Down && (sender.SelectedItems[sender.SelectedItems.Count - 1].Index < sender.Items.Count - 1))
|| (direction == MoveDirection.Up && (sender.SelectedItems[0].Index > 0)));
if (valid)
{
foreach (ListViewItem item in sender.SelectedItems)
{
int index = item.Index + dir;
sender.Items.RemoveAt(item.Index);
sender.Items.Insert(index, item);
sender.Items[index + opp].SubItems[1].Text = (index + opp).ToString();
item.SubItems[1].Text = (index).ToString();
}
}
}
Example:
MoveListViewItems(sourceListView, MoveDirection.Up);
MoveListviewItems(sourceListview, MoveDirection.Down);