2009-01-25 33 views

回答

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線程觸發一個事件(小心調用!)知道他們在做的時候。你可以通過你的UI線程訪問

DialogResult a = ofdThread.DialogResult 

的結果。

1

我知道我有點遲了,但您可以創建一個新的窗體,無邊框,透明或超出顯示範圍,並顯示修改該窗口的文件對話框。

0

這是一箇舊的帖子,但我花了2天達到我想在這裏呈現的結果(帶有「上下文」和完整但簡化的代碼) @Joshua的答案爲我工作(最後,當我把真正的.ConfigureAwait(true),看第一個代碼示例)。也許我能夠根據MSDN Threading Model的長文章寫出更少的行,我仍然需要再次閱讀。

我的上下文是WPF(基本MVVM),我必須選擇一個文件才能寫入一些.CSV備份(datagrid)。我需要的是,(部件)函數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()啓動(異步地)的SaveFileDialogShowDialog()在另一個線程,以便主UI線程/窗口(... ++)既沒有被阻塞也沒有被禁用,因爲它們只是通過簡單的直接調用ShowDialog()TaskCompletionSource<string> tcs不是WPF UI對象,因此可以通過另一個「單個」線程訪問它。

這仍然是我需要進一步研究的領域。我覺得沒有關於這個主題的「終極」文獻/書籍(也許應該再次看一下斯蒂芬克萊裏的書)。此代碼至少應該覆蓋上c-sharp-asynchronous-call-without-endinvoke

話題來提高它的工作原理與命名空間的Microsoft.Win32