2010-01-10 20 views
9

Estoy intentando arrastrar un elemento al explorador.
El elemento debería dar como resultado una descarga de archivos, así que he usado un ejemplo que encontré en la web para descargar el archivo usando un CustomDataObject que llama a un evento cuando realmente necesita la transmisión, y luego mi aplicación hace el pesado levantando y realiza la descarga.
Ha funcionado bien en una operación similar de Portapapeles.arrastre a otro proceso

La descarga del archivo real también causa algunos cambios de la interfaz de usuario en mi aplicación. En su mayoría, un icono de "trabajo" cambia en el formulario y también un globo emergente en caso de error.

En la operación del portapapeles acabo de utilizar InvokeRequired y BeginInvoke cuando sea necesario, para asegurarme de que los cambios de la interfaz de usuario ocurran en el hilo principal. En la operación de arrastre, el hilo de la interfaz de usuario está esperando el retorno del DoDragDrop, mientras que el evento que se genera con el CustomDataObject está siendo llamado en un hilo diferente. Cuando trato de llamar al BeginInvoke o al Invoke, el hilo de la interfaz de usuario todavía está esperando y no puedo terminar la caída.

¿Hay alguna muestra, o una mejor práctica recomendada, sobre cómo permitir el arrastre y la extracción entre aplicaciones, mientras se accede a la interfaz de usuario de la aplicación de origen?

ACTUALIZACIÓN

here es el artículo original con el CodeProject DataObjectEx he modificado para mi propio uso. Acabo de cambiar el método GetFileContents para llamar a un método virtual que devuelve un Stream que contiene los datos del archivo, heredados de la clase, y anula ese método virtual para obtener el archivo de la web. El problema surgió cuando quería cambiar cosas en la interfaz de usuario, mientras obtenía el archivo. Como dije antes, el hilo principal de UI todavía está "atascado" en la llamada al método DoDragDrop, por lo que no puedo invocarlo a tiempo para realizar los cambios de UI necesarios para el hilo del trabajador antes y después de descargar el archivo.

+1

Dudo que obtenga una respuesta útil hasta que describa qué tipo de animal es un "CustomDataObject" y cómo se las arregla para ejecutar el código en su aplicación. –

+0

Buscaré y encontraré el ejemplo de código que utilicé en la red –

Respuesta

1

Si se trata de una aplicación WinForms estándar, entonces todo lo que realmente necesita hacer en su aplicación es agregar manejadores de eventos en su Formulario para DragEnter y DragDrop.

Dentro de DragEnter, tendrá que comprobar el tipo de objeto para asegurarse de que es un nombre de archivo:

private void MyForm_DragEnter(object sender, DragEventArgs e) 
{ 
    if (e.Data.GetDataPresent(DataFormats.FileDrop)) 
    { 
     string[] files = e.Data.GetData(DataFormats.FileDrop) as string[]; 
     if (files != null) 
     { 
      // Do additional checks here if needed, like check extensions 
      e.Effect = DragDropEffects.Copy; 
      return; 
     } 
    } 

    e.Effect = DragDropEffects.None; 
} 

A continuación, en el controlador DragDrop, yo simplemente almacenar fuera los nombres de archivo, y luego activar un temporizador. Esto permite que DragDrop regrese inmediatamente, de modo que la otra aplicación (en su ejemplo, el Explorador de Windows) no se cuelgue mientras realiza cualquier procesamiento en el archivo, lo que puede llevar tiempo. La fuente de arrastre no devolverá hasta que DragDrop finalice.

private void MyForm_DragDrop(object sender, DragEventArgs e) 
{ 
    string[] files = e.Data.GetData(DataFormats.FileDrop) as string[]; 
    if (files != null) 
    { 
     _filesToProcess.Text = files[0]; // Assuming this is declared at the Form level 

     // Schedule a timer to fire in a few miliseconds as a simple asynchronous method 
     _DragDropTimer.Interval = 50; 
     _DragDropTimer.Enabled = true; 
     _DragDropTimer.Start(); 
     Activate(); // Activates the form and gives it focus 
    } 
} 
1

que tenían el mismo problema y encontró que System.Windows.Forms.Control.DoDragDrop ignorado aplicación de mi forma de IAsyncOperation de COM, en lugar de utilizar la aplicación DataObject del WinForm de IDataObject internamente. Desafortunadamente, la clase DataObject de WinForm no implementa IAsyncOperation.

Así que utilicé la implementación VirtualFileDataObject de project de IAsyncOperation, IDataObject, llamando a VirtualFileDataObject.DoDragDrop en lugar de Control.DoDragDrop. Establecí un VirtualFileDataObject.FileDescriptor.StreamContents en un delegado en el que invoco en el subproceso de la interfaz de usuario para informar el progreso mientras descargo el archivo.

Cuestiones relacionadas