2009-01-25 6 views
6

Est-il possible de créer/d'avoir un réseau non-modal? OpenFileDialog J'ai un élément d'interface utilisateur dans la boîte de dialogue principale qui doit toujours être disponible pour que l'utilisateur appuie sur.C# OpenFileDialog Non-Modal possible

Répondre

6

Vous pouvez créer un thread et faire en sorte que le thread héberge OpenFileDialog. Exemple de code manque de tout type de synchronisation, mais cela fonctionne.

public partial class Form1 : Form 
{ 
    OFDThread ofdThread; 

    public Form1() 
    { 
     InitializeComponent(); 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     ofdThread = new OFDThread(); 
     ofdThread.Show(); 
    } 
} 

public class OFDThread 
{ 
    private Thread t; 
    private DialogResult result; 

    public OFDThread() 
    { 
     t = new Thread(new ParameterizedThreadStart(ShowOFD)); 
     t.SetApartmentState(ApartmentState.STA); 
    } 

    public DialogResult DialogResult { get { return this.result; } } 

    public void Show() 
    { 
     t.Start(this); 
    } 

    private void ShowOFD(object o) 
    { 
     OpenFileDialog ofd = new OpenFileDialog(); 
     result = ofd.ShowDialog(); 
    } 
} 

Avec ce code, vous pouvez ajouter quelque chose à déclencher un événement dans votre thread d'interface utilisateur (attention à invoquer!) Pour savoir quand ils sont faits. Vous pouvez accéder au résultat de la boîte de dialogue par

DialogResult a = ofdThread.DialogResult 

à partir de votre thread d'interface utilisateur.

1

Je sais que je suis un peu en retard mais vous pouvez créer un nouveau formulaire, sans bordure, transparent ou en dehors des limites d'affichage et afficher la boîte de dialogue de fichier modifiant cette fenêtre.

0

C'est un vieux post mais je passe 2 jours à atteindre le résultat que je veux présenter ici (avec "contexte" et code complet mais simplifié) La réponse de @Joshua a fonctionné pour moi (enfin quand je mets vrai à .ConfigureAwait (true), voir le premier exemple de code). Peut-être que j'étais capable d'écrire moins de lignes basées sur le long article de MSDN Threading Model que j'ai encore besoin de lire une fois de plus.

Mon contexte est WPF (MVVM de base) et je dois choisir un fichier pour écrire une sauvegarde .CSV (d'un DataGrid). J'ai besoin que le (membre) fonction ChooseFileFromExtension() asynchrone avec un non-bloquant FileDialog

class MainWindowExportToExcelCSV : ICommand 
{ 
    ... 
    public async void Execute(object parameter) 
    { 
     var usr_ctrl = parameter as UserControl; 
     MyFileDialog fd = new MyFileDialog(); 
     const bool WhenIComeBackIStillNeedToAccessUIObjectAndThusINeedToRetrieveMyOriginalUIContext = true; 
     string filename = await fd.ChooseFileFromExtension("CSV files (*.csv)|*.csv|All files (*.*)|*.*").ConfigureAwait(
      WhenIComeBackIStillNeedToAccessUIObjectAndThusINeedToRetrieveMyOriginalUIContext); 

     Visual visual = (Visual)usr_ctrl.Content; 
     for (int i = 0; i < VisualTreeHelper.GetChildrenCount(visual); i++) 
     { 
      //look for datagrid element 
     } 
    } 
} 

et le code pour la classe MyFileDialog

using Microsoft.Win32; 
... 

class MyFileDialog 
{ 
    //https://msdn.microsoft.com/en-us/library/ms741870(v=vs.110).aspx 
    //Article on Threading Model 
    private delegate void OneArgStrDelegate(string str); 

    private void MyExternalDialog(string extensions) 
    { 
     SaveFileDialog fd = new SaveFileDialog(); 
     fd.Filter = extensions; 
     fd.ShowDialog(); 
     tcs.SetResult(fd.FileName); 
    } 

    private TaskCompletionSource<string> tcs; 

    public Task<string> ChooseFileFromExtension(string file_ext) 
    { 
     //Cf Puppet Task in Async in C#5.0 by Alex Davies 
     tcs = new TaskCompletionSource<string>(); 

     OneArgStrDelegate fetcher = new OneArgStrDelegate(this.MyExternalDialog); 
     fetcher.BeginInvoke(file_ext, null, null); 
     return tcs.Task; 
    } 
} 

Les fetcher.BeginInvoke() lancements (de manière asynchrone) le SaveFileDialogShowDialog() dans un autre fil de sorte que l'interface utilisateur principale Thread/Window (... ++) n'est ni bloquée ni désactivée comme elle l'aurait été avec un simple appel direct au ShowDialog(). TaskCompletionSource<string> tcs n'est pas un objet WPF UI, donc son accès par un autre thread "unique" est OK.

C'est encore un domaine que j'ai besoin d'étudier plus avant. Je pense qu'il n'y a pas de documentation/livre «ultime» sur le sujet (peut-être devrait-on revoir les livres comme celui de Stephen Cleary). Ce code devrait être amélioré au moins avec le sujet couvert sur c-sharp-asynchronous-call-without-endinvoke

Il fonctionne avec l'espace de noms FileDialog Microsoft.Win32

Questions connexes