如何将文件拖放到应用程序中?


251

我已经在Borland的Turbo C ++环境中看到了这一点,但是我不确定如何针对正在开发的C#应用​​程序进行此操作。是否有最佳实践或陷阱?


您是指拖放到C#应用程序中还是拖放到C#IDE中?
JamesSugrue

4
当然,C#应用程序也是如此。他想使他的应用程序拖放友好。
SLA80'2

3
有关链接的更多有用答案。
Venkatesh Kumar

Answers:


505

一些示例代码:

  public partial class Form1 : Form {
    public Form1() {
      InitializeComponent();
      this.AllowDrop = true;
      this.DragEnter += new DragEventHandler(Form1_DragEnter);
      this.DragDrop += new DragEventHandler(Form1_DragDrop);
    }

    void Form1_DragEnter(object sender, DragEventArgs e) {
      if (e.Data.GetDataPresent(DataFormats.FileDrop)) e.Effect = DragDropEffects.Copy;
    }

    void Form1_DragDrop(object sender, DragEventArgs e) {
      string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
      foreach (string file in files) Console.WriteLine(file);
    }
  }

56
免责声明:如果您在Windows 7中以管理员身份运行Visual Studio,或者以管理员身份运行程序,则它可能无法在调试中工作。看到这里
Matthieu 2012年

您如何获取文件内容?
Burnsys

3
@Burnsys如果您具有拖动操作的文件路径,则可以使用io.File
Smith

1
gh,不。在设计器中将AllowDrop属性设置为True,然后从那里进行推理。
Hans Passant 2014年

2
(string[])投射对任何FileDrop格式的投稿是否安全?也就是说,是否有可能生成FileDrop会导致的非法强制转换异常的string[]?我在从文档中找出问题时遇到了麻烦。
kdbanman 2015年

140

请注意Windows Vista / Windows 7的安全权限-如果您以管理员身份运行Visual Studio,则在Visual Studio中运行文件时,将无法将非管理员资源管理器窗口中的文件拖到程序中。与拖动相关的事件甚至不会触发!我希望这可以帮助其他人不要浪费自己的时间。


6
@Wayne Uroda:我以为我的代码无法正常工作-哎呀,它给了我一个很大的“ No symbol”,例如en.wikipedia.org/wiki/File:ProhibitionSign2.svg。然后,我看到了这个答案,并以非管理员身份运行VS,并认为它有效!太感谢了。
Derek W

对此,我感激不尽,除非我碰巧找到了这篇文章,否则我会放弃的!它在2017年的Windows 10中与编写时一样有效。
库尔姆

42

在Windows窗体中,设置控件的AllowDrop属性,然后侦听DragEnter事件和DragDrop事件。

DragEnter事件触发时,将参数的值设置为非AllowedEffect空(例如e.Effect = DragDropEffects.Move)。

DragDrop事件触发时,你会得到一个字符串列表。每个字符串都是要删除的文件的完整路径。


16

您需要注意一个陷阱。您在拖放操作中作为DataObject传递的任何类都必须是可序列化的。因此,如果您尝试传递一个对象,但该对象不起作用,请确保可以对其进行序列化,因为这几乎可以肯定是问题所在。这吸引了我几次!


14

另一个陷阱:

调用Drag-events的框架代码吞没了所有异常。您可能会认为事件代码运行顺畅,而到处都是异常。您看不到它们,因为框架会窃取它们。

这就是为什么我总是在这些事件处理程序中放置try / catch的原因,所以我才知道它们是否抛出任何异常。我通常放一个Debugger.Break();。在捕获部分。

发布之前,经过测试,如果一切似乎正常,我将其删除或替换为真正的异常处理。


9

另一个常见的陷阱是您可以忽略Form DragOver(或DragEnter)事件。我通常使用Form的DragOver事件来设置AllowedEffect,然后使用特定控件的DragDrop事件来处理放置的数据。


7

这是我用来删除文件和/或充满文件的文件夹的内容。就我而言,我仅过滤*.dwg文件,并选择包括所有子文件夹。

fileList是一种IEnumerable或类似的在我的情况下被绑定到WPF控件...

var fileList = (IList)FileList.ItemsSource;

有关该技巧的详细信息,请参见https://stackoverflow.com/a/19954958/492

放置处理程序...

  private void FileList_OnDrop(object sender, DragEventArgs e)
  {
    var dropped = ((string[])e.Data.GetData(DataFormats.FileDrop));
    var files = dropped.ToList();

    if (!files.Any())
      return;

    foreach (string drop in dropped)
      if (Directory.Exists(drop))
        files.AddRange(Directory.GetFiles(drop, "*.dwg", SearchOption.AllDirectories));

    foreach (string file in files)
    {
      if (!fileList.Contains(file) && file.ToLower().EndsWith(".dwg"))
        fileList.Add(file);
    }
  }

3

设计器中提供了Judah Himango和Hans Passant的解决方案(我目前正在使用VS2015):

在此处输入图片说明

在此处输入图片说明


0

您可以在WinForms和WPF中实现拖放。

  • WinForm(从应用程序窗口拖动)

您应该添加mousemove事件:

private void YourElementControl_MouseMove(object sender, MouseEventArgs e)

    {
     ...
         if (e.Button == MouseButtons.Left)
         {
                 DoDragDrop(new DataObject(DataFormats.FileDrop, new string[] { PathToFirstFile,PathToTheNextOne }), DragDropEffects.Move);
         }
     ...
    }
  • WinForm(拖动到应用程序窗口)

您应该添加DragDrop事件:

私人void YourElementControl_DragDrop(object sender,DragEventArgs e)

    {
       ...
       foreach (string path in (string[])e.Data.GetData(DataFormats.FileDrop))
            {
                File.Copy(path, DirPath + Path.GetFileName(path));
            }
       ...
    }

源代码完整

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.