2010-01-10 4 views
9

J'essaie de faire glisser un élément dans l'explorateur.
L'élément devrait entraîner un téléchargement de fichier, donc j'ai utilisé un exemple que j'ai trouvé sur le web pour télécharger le fichier en utilisant un CustomDataObject qui appelle un événement quand il a réellement besoin du flux, puis mon application fait le lourd soulever et effectue le téléchargement.
Cela fonctionne très bien dans une opération similaire du Presse-papiers.glisser dans un autre processus

Le téléchargement du fichier entraîne également certaines modifications de l'interface utilisateur dans mon application. Surtout une icône de "travail" changeant sur le formulaire, et aussi une bulle popup en cas d'erreur.

Dans l'opération de presse-papiers, j'ai simplement utilisé InvokeRequired et BeginInvoke si nécessaire, pour m'assurer que ces changements d'interface se produisent sur le fil principal. Dans l'opération glisser, le thread UI attend le retour de DoDragDrop, tandis que l'événement soulevé par le CustomDataObject est appelé sur un thread différent. Lorsque j'essaie d'appeler BeginInvoke ou Invoke le thread UI attend toujours, et je ne peux pas terminer la baisse.

Existe-t-il un exemple, ou une pratique recommandée recommandée, sur la façon d'autoriser le glisser-déposer d'application croisée tout en accédant à l'interface utilisateur de l'application source?

MISE À JOUR

here est l'article CodeProject d'origine avec le DataObjectEx j'ai modifié pour mon propre usage. Je viens de changer la méthode GetFileContents pour appeler une méthode virtuelle qui renvoie un Stream contenant les données du fichier, héritées de la classe, et substitué cette méthode virtuelle pour obtenir le fichier du web. Le problème est survenu lorsque j'ai voulu changer des choses dans l'interface utilisateur, tout en obtenant le fichier. Comme je l'ai dit plus tôt - le thread principal de l'interface utilisateur est toujours bloqué à l'appel de la méthode DoDragDrop, donc je ne peux pas l'invoquer à temps pour faire les changements d'interface utilisateur nécessaires par le thread de travail avant et après le téléchargement.

+1

Je doute que vous obtiendrez une réponse utile jusqu'à ce que vous décriviez quel type d'animal un "CustomDataObject" est et comment il parvient à exécuter du code dans votre application. –

+0

Je vais creuser et trouver l'échantillon de code que j'ai utilisé sur le net –

Répondre

1

S'il s'agit d'une application WinForms standard, tout ce que vous devez faire dans votre application est d'ajouter des gestionnaires d'événements dans votre formulaire pour DragEnter et DragDrop.

intérieur de DragEnter, vous aurez envie de vérifier le type d'objet pour vous assurer qu'il est un nom de fichier:

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

Ensuite, dans votre gestionnaire DragDrop, je voudrais simplement stocker hors les noms de fichiers, puis activer une minuterie. Cela permet à DragDrop de revenir immédiatement, de sorte que l'autre application (dans votre exemple, Windows Explorer) ne se bloque pas pendant que vous effectuez un traitement sur le fichier, ce qui peut prendre du temps. Le Drag Source ne renverra pas jusqu'à ce que DragDrop se termine.

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

J'ai eu le même problème et a constaté que System.Windows.Forms.Control.DoDragDrop ignoré ma mise en œuvre du formulaire de IAsyncOperation de COM, en utilisant à la place du DataObject WinForm la mise en œuvre de IDataObject interne. Malheureusement, la classe DataObject de WinForm n'implémente pas IAsyncOperation.

J'ai donc utilisé l'implémentation VirtualFileDataObject de project de IAsyncOperation, IDataObject, en appelant VirtualFileDataObject.DoDragDrop au lieu de Control.DoDragDrop. J'ai défini un VirtualFileDataObject.FileDescriptor.StreamContents à un délégué où j'appelle sur le thread d'interface utilisateur pour signaler la progression lors du téléchargement du fichier.

Questions connexes