拖动多个文件

Drag multiple files

我有一个包含文件路径列表的列表框,其中 属性 SelectionMode 设置为 MultiExtended。因此,我可以 select 此列表中的许多项。

现在,我想从目标文件夹中的这些路径开始拖放文件。

我的代码:

private void Form1_Load(object sender, EventArgs e)
{
    // populate the FileList
    // i.e. FileList.Items.Add("d:/Samples/file-00" + i + ".wav");

    this.FileList.MouseDown += new MouseEventHandler(FileList_MouseDown);
    this.FileList.DragOver += new DragEventHandler(FileList_DragOver);
}

void FileList_DragOver(object sender, DragEventArgs e)
{
    e.Effect = DragDropEffects.Copy;
}

void FileList_MouseDown(object sender, MouseEventArgs e)
{
    List<string> filesToDrag = new List<string>();
    foreach (var item in FileList.SelectedItems)
    {
        filesToDrag.Add(item.ToString().Trim());
    }

    this.FileList.DoDragDrop(new DataObject(DataFormats.FileDrop, 
                             filesToDrag.ToArray()), DragDropEffects.Copy);
}

如果我 select 并将 1 个单曲 line/file 从 ListBox 拖放到目标文件夹,它就完美了。

相反,如果我执行多个 selection 并尝试拖放,它只能 select 我开始拖动的那一行。似乎 MouseDown 阻止了这个?

你会如何解决这个问题?

是的...我认为没有解决该问题的好方法。当您再次单击以启动拖动时,它将切换该项目。在鼠标 按住并移动 .

之前,我们不知道用户实际上想要进行拖动

一个可能的解决方案是从其他东西启动 drag/drop,只是以某种方式真正清楚地表明用户应该拖动什么。这里我使用的是标签而不是列表框:

    void label1_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.Button == System.Windows.Forms.MouseButtons.Left)
        {
            List<string> filesToDrag = new List<string>();
            foreach (var item in FileList.SelectedItems)
            {
                filesToDrag.Add(item.ToString().Trim());
            }
            if (filesToDrag.Count > 0)
            {
                this.FileList.DoDragDrop(new DataObject(DataFormats.FileDrop,
                                     filesToDrag.ToArray()), DragDropEffects.Copy);
            }
            else
            {
                MessageBox.Show("Select Files First!");
            }
        }
    }

您必须对鼠标按下和鼠标移动活动挑剔。当它位于列表框的图形矩形内时,您将需要正常的行为。当它超出此矩形的边界时,您将需要 drag/drop 功能。您可以试试下面的伪代码:

MouseDown(sender, e)
{
    var x = <your sender as control>.ItemFromPoint(.....)
    this.mouseLocation = x == null ? x : e.Location;
}

MouseMove(sender, e)
{
    if control rectangle doesn't contain the current location then
        <your sender as control>.Capture = false
        DoDragDrop
}

使用 ListBox 执行此操作似乎非常困难。其实我还没有找到解决办法..

改用ListView!这很容易,使用 ItemDrag 事件,并且是 更好的 控件。我无法计算我必须从 [=30= 更改的频率] ListBoxListView 因为我需要这个或那个 'little' 额外的..

您的代码已移至 ItemDrag:

private void listView1_ItemDrag(object sender, ItemDragEventArgs e)
{
    List<string> filesToDrag = new List<string>();
    foreach (var item in listView1.SelectedItems)
    {
        filesToDrag.Add(item.ToString().Trim());
    }

    this.listView1.DoDragDrop(new DataObject(DataFormats.FileDrop,
                                filesToDrag.ToArray()), DragDropEffects.Copy);
}

请注意,这仅解决了 MouseDown 更改选择的问题。它本身并不能保证实际复制会起作用。

我发现 this 有趣的文章提出了解决方案。也许你不需要它,因为你已经说过你已经复制了一个已经工作的文件..