Drag drop ListView Item from one listView to another

SoyDuck picture SoyDuck · Jul 2, 2016 · Viewed 8.5k times · Source

Right now, i am able to drag an item from listView 1 to listView 2. how do you clone/copy/move the item's data across? Gif of what i mean here

widgetList is listView1. aka the list on the far right.

private void fillWidgetList()
    {
        widgetList.Groups.Add(new ListViewGroup("System", HorizontalAlignment.Left));

        var cpu = new ListViewItem { Text = "CPU", Tag = "", Group = widgetList.Groups["System"] };
        var ram = new ListViewItem { Text = "RAM", Tag = "", Group = widgetList.Groups["System"] };
        widgetList.Items.Add(cpu);
        widgetList.Items.Add(ram);
    }

widgetCollectionList is listView2. aka the list in the middle.

private void widgetList_ItemDrag(object sender, ItemDragEventArgs e)
    {
        DoDragDrop(e.Item, DragDropEffects.Move);
        // am i suppose to save the dragged item somewhere?
    }

    private void widgetCollectionList_DragEnter(object sender, DragEventArgs e)
    {
        //e.Effect = DragDropEffects.Copy;

        if (e.Data.GetDataPresent(typeof(ListViewItem)))
        {
            e.Effect = DragDropEffects.Move;
        }
    }

    private void widgetCollectionList_DragDrop(object sender, DragEventArgs e)
    {
        widgetCollectionList.Items.Add(e.Data.ToString()); // What do i replace this with?
    }

    private void WidgetMaker_Load(object sender, System.EventArgs e)
    {
        widgetCollectionList.AllowDrop = true;
        widgetCollectionList.DragDrop += new DragEventHandler(widgetCollectionList_DragDrop);
    }

Answer

Ňɏssa Pøngjǣrdenlarp picture Ňɏssa Pøngjǣrdenlarp · Jul 2, 2016

You are almost there. You arent casting the objects passed in e.Data back to an LVI and an LVI object can only belong to one ListView. So, to move them, you need to remove them from the old one first; to copy them, you need to clone them. (Groups make this much more interesting: can a veggie item be dropped onto the fruit group?)

I expanded it to allow it to move all the selected items so more than one can be moved at a time. Its easy to remove if that's not what you want.

private void lv_ItemDrag(object sender, ItemDragEventArgs e)
{
    // create array or collection for all selected items
    var items = new List<ListViewItem>();
    // add dragged one first
    items.Add((ListViewItem)e.Item);
    // optionally add the other selected ones
    foreach (ListViewItem lvi in lv.SelectedItems)
    {
        if (!items.Contains(lvi))
        {
            items.Add(lvi);
        }
    }
    // pass the items to move...
    lv.DoDragDrop(items, DragDropEffects.Move);
}

// this SHOULD look at KeyState to disallow actions not supported
private void lv2_DragOver(object sender, DragEventArgs e)
{
    if (e.Data.GetDataPresent(typeof(List<ListViewItem>)))
    {
        e.Effect = DragDropEffects.Move;
    }
}

private void lv2_DragDrop(object sender, DragEventArgs e)
{
    if (e.Data.GetDataPresent(typeof(List<ListViewItem>)))
    {
        var items = (List<ListViewItem>)e.Data.GetData(typeof(List<ListViewItem>));
        // move to dest LV
        foreach (ListViewItem lvi in items)
        {
            // LVI obj can only belong to one LVI, remove
            lvi.ListView.Items.Remove(lvi);
            lv2.Items.Add(lvi);
        }
    }
}