¿Cómo arrastro y suelto archivos en una aplicación?

251

He visto esto en el entorno Turbo C ++ de Borland , pero no estoy seguro de cómo hacerlo para una aplicación C # en la que estoy trabajando. ¿Hay mejores prácticas o trampas a tener en cuenta?

Uwe Keim
fuente
¿Quiere decir arrastrar y soltar en una aplicación C # o en el IDE C #?
JamesSugrue
44
De cource, aplicación C #. Quiere que su aplicación sea fácil de arrastrar y soltar.
SLA80
3
Más respuestas útiles en el enlace .
Venkatesh Kumar

Respuestas:

505

Algún código de muestra:

  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);
    }
  }
Hans Passant
fuente
56
Descargo de responsabilidad: puede que no funcione en depuración si ejecuta Visual Studio como administrador en Windows 7, o si ejecuta su programa como administrador. Ver aquí
Matthieu
¿Cómo se obtiene el contenido de los archivos?
Burnsys
3
@ Burnsys si tiene la ruta de archivo de la operación de arrastre, puede leer usandoio.File
Smith
1
Uf, no Establezca la propiedad AllowDrop en True en el diseñador y razone desde allí.
Hans Passant
2
¿Es (string[])seguro el yeso para cualquier FileDropcaída con formato? Es decir, ¿es posible generar un FileDropque provocará una excepción de lanzamiento ilegal string[]? Tengo problemas para descifrar eso de los documentos .
kdbanman
140

Tenga en cuenta los derechos de seguridad de Windows Vista / Windows 7: si está ejecutando Visual Studio como administrador, no podrá arrastrar archivos desde una ventana del explorador que no sea administrador a su programa cuando lo ejecute desde Visual Studio. ¡Los eventos relacionados con la resistencia ni siquiera se dispararán! Espero que esto ayude a alguien más a no perder horas de su vida ...

Wayne Uroda
fuente
66
@Wayne Uroda: pensé que mi código no funcionaba, diablos, me estaba dando un gran "Sin símbolo" como este en.wikipedia.org/wiki/File:ProhibitionSign2.svg . Luego vi esta respuesta y ejecuté VS como no administrador y ¡listo para que funcione! Un millón de gracias.
Derek W
No puedo agradecerles lo suficiente por esto, ¡me habría rendido a menos que encontrara esta publicación! Es tan válido en Windows 10 en 2017 como lo fue cuando lo escribió.
Culme
42

En Windows Forms, configure la propiedad AllowDrop del control, luego escuche el evento DragEnter y el evento DragDrop.

Cuando se DragEnterdesencadena el evento, establezca los argumentos AllowedEffecten algo diferente a ninguno (por ejemplo e.Effect = DragDropEffects.Move).

Cuando DragDropse active el evento, obtendrá una lista de cadenas. Cada cadena es la ruta completa al archivo que se descarta.

Judá Gabriel Himango
fuente
16

Necesitas estar al tanto de una trampa. Cualquier clase que pase como DataObject en la operación de arrastrar / soltar debe ser serializable. Entonces, si intenta pasar un objeto y no funciona, asegúrese de que se pueda serializar, ya que ese es casi seguro el problema. ¡Esto me ha pillado un par de veces!

Phil Wright
fuente
14

Otro problema más:

El código marco que llama a los eventos de arrastre se traga todas las excepciones. Puede pensar que su código de evento se ejecuta sin problemas, mientras que está generando excepciones por todas partes. No puedes verlos porque el marco los roba.

Es por eso que siempre pongo un try / catch en estos controladores de eventos, solo para saber si lanzan alguna excepción. Usualmente pongo un Debugger.Break (); en la parte de captura.

Antes del lanzamiento, después de la prueba, si todo parece comportarse, elimino o reemplazo estos con un manejo de excepciones real.

Guge
fuente
9

Otro problema común es pensar que puede ignorar los eventos Form DragOver (o DragEnter). Normalmente uso el evento DragOver del formulario para establecer el efecto permitido y luego el evento DragDrop de un control específico para manejar los datos descartados.

Craig Eddy
fuente
7

Aquí hay algo que solía soltar archivos y / o carpetas llenas de archivos. En mi caso, estaba filtrando *.dwgsolo archivos y elegí incluir todas las subcarpetas.

fileListes un IEnumerableo similar En mi caso estaba vinculado a un control WPF ...

var fileList = (IList)FileList.ItemsSource;

Consulte https://stackoverflow.com/a/19954958/492 para obtener detalles sobre ese truco.

The Drop Handler ...

  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);
    }
  }
CAD bloke
fuente
3

La solución de Judah Himango y Hans Passant está disponible en el Diseñador (actualmente estoy usando VS2015):

ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí

Roland
fuente
0

Puede implementar Drag & Drop en WinForms y WPF.

  • WinForm (Arrastrar desde la ventana de la aplicación)

Debe agregar el evento 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 (Arrastre a la ventana de la aplicación)

Debe agregar el evento DragDrop:

private void YourElementControl_DragDrop (remitente del objeto, DragEventArgs e)

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

Fuente con código completo .

Ernest Rutherford
fuente