Moving ListViewItems Up & Down

前端 未结 6 2836
你的背包
你的背包 2021-02-20 16:45

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

6条回答
  •  予麋鹿
    予麋鹿 (楼主)
    2021-02-20 17:34

    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:

    1. Implement a wrap-around reshuffle (i.e top item goes to the bottom)
    2. 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();
        }
    }
    

    Edit 2:

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

提交回复
热议问题