Pergunta

É possível criar/ter um .NET OpenFiledialog não modal Eu tenho um elemento de interface do usuário na caixa de diálogo principal que sempre precisa estar disponível para o usuário pressionar.

Foi útil?

Solução

Não, OpenFiledialog e Savefiledialog ambos são derivados de Filedialog, que é inerentemente modal, então (até onde eu sei), não há como criar uma versão não modal de nenhum deles.

Outras dicas

Você pode criar um thread e fazer com que o thread hospede o OpenFiledialog. O código de exemplo não tem qualquer tipo de sincronização, mas funciona.

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

Com este código, você pode adicionar algo para disparar um evento no seu tópico da interface do usuário (tenha cuidado ao invocar!) Para saber quando eles terminarem. Você pode acessar o resultado da caixa de diálogo

DialogResult a = ofdThread.DialogResult

do seu tópico da interface do usuário.

Sei que estou um pouco tarde, mas você pode criar um novo formulário, sem fronteiras, transparente ou fora dos limites da tela e mostrar a caixa de diálogo de arquivo modificando essa janela.

É um post antigo, mas passo 2 dias atingindo o resultado que quero apresentar aqui (com "contexto" e código completo, mas simplificado) a resposta de @Joshua funcionou para mim (finalmente quando eu coloquei fiéis ao .configurewait (verdadeiro) , consulte a primeira amostra de código). Talvez eu tenha sido capaz de escrever menos linhas com base no longo artigo do MSDN Modelo de rosqueamento que ainda preciso ler mais uma vez.

Meu contexto é WPF (MVVM básico) e devo escolher um arquivo para gravar algum backup .csv (de um datagrid). Eu preciso da função (membro) ChooseFileFromExtension() ser assíncrono com um arquivo não bloqueador

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 o código para a 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;
    }
}

o fetcher.BeginInvoke() lançamentos (assíncronos) o SaveFileDialog ShowDialog() em outro tópico para que o encadeamento / janela principal da interface do usuário (... ++) não seja bloqueado nem desativado, pois teriam sido com uma simples chamada direta para ShowDialog(). TaskCompletionSource<string> tcs não é um objeto WPF UI, portanto, seu acesso por outro thread "single" está ok.

Ainda é um campo que eu preciso estudar mais. Eu sinto que não há documentação/livro "final" sobre o assunto (talvez deva dar uma segunda olhada em livros como o de Stephen Cleary novamente). Este código deve ser melhorado pelo menos com o tópico abordado C-sharp-asincrome-call-without-endinvoke

Funciona com o arquivo Filedialog do namespace microsoft.win32

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top