Domanda

È possibile creare/avere un OpenFileDialog .net non modale. Ho un elemento dell'interfaccia utente nella finestra di dialogo principale che deve essere sempre disponibile per la pressione dell'utente.

È stato utile?

Soluzione

NO, OpenFileDialog E Finestra di dialogo SalvaFile sono entrambi derivati ​​da FileDialog, che è intrinsecamente modale, quindi (per quanto ne so) non c'è modo di creare una versione non modale di nessuno dei due.

Altri suggerimenti

Puoi creare un thread e fare in modo che il thread ospiti OpenFileDialog. Il codice di esempio non ha alcun tipo di sincronizzazione ma funziona.

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

Con questo codice potresti aggiungere qualcosa per generare un evento nel tuo thread dell'interfaccia utente (fai attenzione a invocare!) per sapere quando hanno finito. Puoi accedere al risultato della finestra di dialogo da

DialogResult a = ofdThread.DialogResult

dal thread dell'interfaccia utente.

So di essere un po 'in ritardo, ma potresti creare una nuova forma, senza bordi, trasparente o al di fuori dei limiti di visualizzazione e mostrare la finestra di dialogo del file modificando quella finestra.

È un vecchio post ma passo 2 giorni a raggiungere il risultato che voglio presentare qui (con " contesto " e codice completo ma semplificato) La risposta di @Joshua ha funzionato per me (finalmente quando ho inserito true in .ConfigureAwait (true), vedi il primo esempio di codice). Forse sono stato in grado di scrivere meno righe in base al lungo articolo di MSDN Threading Model che devo ancora leggere ancora.

Il mio contesto è WPF (MVVM di base) e devo scegliere un file per scrivere un backup .CSV (di un datagrid). Ho bisogno che la funzione (membro) ChooseFileFromExtension() sia asincrona con un FileDialog non bloccante

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

e il codice per 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;
    }
}

Il fetcher.BeginInvoke() avvia (in modo asincrono) il SaveFileDialog ShowDialog() in un altro thread in modo che il thread / finestra dell'interfaccia utente principale (... ++) non siano né bloccati né disabilitati come sarebbero stati con un semplice diretto chiama a TaskCompletionSource<string> tcs. <=> non è un oggetto UI WPF, quindi il suo accesso da un altro " singolo " la discussione è OK.

È ancora un campo che devo studiare ulteriormente. Sento che non c'è & Quot; ultimate & Quot; documentazione / libro sull'argomento (forse dovrebbe dare una seconda occhiata a libri come quello di Stephen Cleary di nuovo). Questo codice dovrebbe essere migliorato almeno con l'argomento trattato in c-sharp-asynchronous-call-without-endinvoke

Funziona con il FileDialog dello spazio dei nomi Microsoft.Win32

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top