Come trascinare e rilasciare i file in un'applicazione?


251

L'ho visto fatto nell'ambiente Turbo C ++ di Borland , ma non sono sicuro di come procedere per un'applicazione C # su cui sto lavorando. Ci sono best practice o gotcha da tenere in considerazione?


Intendi il trascinamento della selezione in un'applicazione C # o nell'IDE C #?
JamesSugrue,

4
Di cortesia, applicazione C #. Vuole rendere la sua applicazione drag & drop amichevole.
SLA80,

3
Risposte più utili al link .
Venkatesh Kumar,

Risposte:


505

Qualche codice di esempio:

  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
Dichiarazione di non responsabilità: potrebbe non funzionare nel debug se si esegue Visual Studio come amministratore in Windows 7 o se si esegue il programma come amministratore. Vedi qui
Matthieu,

Come si ottiene il contenuto dei file?
Burnsys,

3
@Burnsys se si dispone del percorso file dall'operazione di trascinamento, è possibile leggere utilizzandoio.File
Smith,

1
Uh, no. Impostare la proprietà AllowDrop su True nella finestra di progettazione e ragionare da lì.
Hans Passant,

2
Il (string[])cast è sicuro per qualsiasi FileDropdrop formattato? Cioè, è possibile generare un FileDropche provocherà un'eccezione di cast illegale string[]? Sto avendo problemi a capirlo dai documenti .
kdbanman,

140

Prestare attenzione ai diritti di sicurezza di Windows Vista / Windows 7: se si esegue Visual Studio come amministratore, non sarà possibile trascinare i file da una finestra Explorer non amministratore nel programma quando lo si esegue da Visual Studio. Gli eventi relativi al trascinamento non si attivano nemmeno! Spero che questo aiuti qualcun altro là fuori a non perdere ore della sua vita ...


6
@Wayne Uroda: Pensavo che il mio codice non funzionasse - diamine mi stava dando un grande "Nessun simbolo" come questo en.wikipedia.org/wiki/File:ProhibitionSign2.svg . Poi ho visto questa risposta e ho eseguito VS come non amministratore e presto funziona! Grazie mille.
Derek W,

Non posso ringraziarti abbastanza per questo, mi sarei arreso se non mi fosse capitato di trovare questo post! È valido in Windows 10 nel 2017 come quando l'hai scritto.
Culme,

42

In Windows Form, imposta la proprietà AllowDrop del controllo, quindi ascolta l'evento DragEnter e l'evento DragDrop.

Quando l' DragEnterevento si attiva, imposta l'argomento AllowedEffectsu qualcosa di diverso da nessuno (ad es e.Effect = DragDropEffects.Move.).

Quando l' DragDropevento si attiva, otterrai un elenco di stringhe. Ogni stringa è il percorso completo del file che viene eliminato.


16

Devi essere consapevole di un gotcha. Qualsiasi classe che passi come DataObject nell'operazione di trascinamento della selezione deve essere serializzabile. Quindi, se provi a passare un oggetto e non funziona, assicurati che possa essere serializzato poiché questo è quasi sicuramente il problema. Questo mi ha colpito un paio di volte!


14

Ancora un altro gotcha:

Il codice del framework che chiama gli eventi Drag ingoia tutte le eccezioni. Potresti pensare che il tuo codice evento stia funzionando senza intoppi, mentre sta scatenando eccezioni dappertutto. Non puoi vederli perché il framework li ruba.

Ecco perché metto sempre un tentativo in questi gestori di eventi, solo per sapere se generano eccezioni. Di solito metto un Debugger.Break (); nella parte di cattura.

Prima del rilascio, dopo il test, se tutto sembra funzionare, rimuovo o sostituisco questi con una vera gestione delle eccezioni.


9

Un altro gotcha comune sta pensando che puoi ignorare gli eventi Form DragOver (o DragEnter). In genere utilizzo l'evento DragOver del form per impostare il AllowEffect e quindi l'evento DragDrop di un controllo specifico per gestire i dati rilasciati.


7

Ecco qualcosa che ho usato per eliminare file e / o cartelle piene di file. Nel mio caso stavo filtrando *.dwgsolo i file e ho scelto di includere tutte le sottocartelle.

fileListè un IEnumerableo simile Nel mio caso era associato a un controllo WPF ...

var fileList = (IList)FileList.ItemsSource;

Vedi https://stackoverflow.com/a/19954958/492 per i dettagli di quel trucco.

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

3

La soluzione di Judah Himango e Hans Passant è disponibile in Designer (attualmente sto usando VS2015):

inserisci qui la descrizione dell'immagine

inserisci qui la descrizione dell'immagine


0

È possibile implementare il trascinamento della selezione in WinForms e WPF.

  • WinForm (trascina dalla finestra dell'app)

Devi aggiungere l'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 (trascina nella finestra dell'app)

È necessario aggiungere l'evento DragDrop:

void privato YourElementControl_DragDrop (mittente oggetto, DragEventArgs e)

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

Sorgente con codice completo .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.