7

是否可以创建/拥有一个非模态的 .net OpenFileDialog 我在主对话框中有一个 UI 元素,它总是需要用户按下。

4

4 回答 4

7

不,OpenFileDialogSaveFileDialog都是从FileDialog派生的,它本质上是模态的,所以(据我所知)没有办法创建它们中的任何一个的非模态版本。

于 2009-01-25T23:15:25.373 回答
6

您可以创建一个线程并让该线程托管 OpenFileDialog。示例代码缺少任何类型的同步,但它可以工作。

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

使用此代码,您可以添加一些内容以在您的 UI 线程中触发事件(小心调用!)以了解它们何时完成。您可以通过以下方式访问对话框的结果

DialogResult a = ofdThread.DialogResult

从您的 UI 线程。

于 2009-07-23T21:33:39.513 回答
1

我知道我有点晚了,但您可以创建一个新表单,无边框、透明或超出显示范围,并显示修改该窗口的文件对话框。

于 2011-03-22T13:45:21.540 回答
0

这是一篇旧帖子,但我花了 2 天时间才达到我想在这里展示的结果(带有“上下文”和完整但简化的代码)@Joshua 的答案对我有用(最后当我把 true 设置为 .ConfigureAwait(true) ,请参见第一个代码示例)。也许我可以根据我仍然需要再次阅读的MSDN Threading Model的长文写更少的行。

我的上下文是 WPF(基本 MVVM),我必须选择一个文件才能编写一些 .CSV 备份(数据网格的)。我需要(成员)函数ChooseFileFromExtension()与非阻塞 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
        }
    }
}

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

在另一个线程中fetcher.BeginInvoke()(异步)启动SaveFileDialog ShowDialog(),以便主 UI 线程/窗口(...++)既不会被阻塞也不会被禁用,因为它们本来可以通过简单的直接调用ShowDialog(). TaskCompletionSource<string> tcs不是 WPF UI 对象,因此可以通过另一个“单个”线程访问它。

这仍然是我需要进一步研究的领域。我觉得没有关于这个主题的“终极”文档/书籍(也许应该再看一下斯蒂芬克利里的书)。至少应使用c-sharp-asynchronous-call-without-endinvoke 中涵盖的主题来改进此代码

它适用于命名空间 Microsoft.Win32 的 FileDialog

于 2017-02-28T15:52:18.203 回答