C#OpenFileDialog非模态可能

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

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

您可以创建一个线程并让线程托管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线程。

我知道我有点迟了但你可以创建一个新的表单,无边框,透明或在显示边界之外,并显示修改该窗口的文件对话框。

这是一个老post,但我花了2天时间达到了我想在这里呈现的结果(带有“上下文”和完整但简化的代码)@Joshua的答案对我有用(最后当我把它变为现实.ConfigureAwait(true) ,请参阅第一个代码示例)。 也许我能够根据MSDN 线程模型的长篇文章编写更少的行,我仍然需要再次阅读。

我的上下文是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 tcs; public Task ChooseFileFromExtension(string file_ext) { //Cf Puppet Task in Async in C#5.0 by Alex Davies tcs = new TaskCompletionSource(); OneArgStrDelegate fetcher = new OneArgStrDelegate(this.MyExternalDialog); fetcher.BeginInvoke(file_ext, null, null); return tcs.Task; } } 

fetcher.BeginInvoke()在另一个线程中启动(异步) SaveFileDialog ShowDialog() ,这样主UI线程/窗口(... ++)既不会被阻止也不会被禁用,因为它们只是简单地直接调用ShowDialog()TaskCompletionSource tcs不是WPF UI对象,因此可以通过另一个“单个”线程进行访问。

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

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