2012-03-07 279 views
0

如果您不熟悉Ookii.Dialogs,我建議您先look at this web page。它是開放源代碼,您可以在那裏找到源代碼,編譯後的二進制文件和示例應用程序。Ookii.Dialogs - 確保在進度對話框上方出現另一個對話框

在我的應用程序,我使用Ookii.Dialogs.Wpf.ProgressDialog的ShowDialog(本)進展對話,做對文件進行一些處理(始終是應用程序的主窗口)。正如預期的那樣,進度對話框實際上變得可見之前需要一秒左右的時間(即使它已經在處理我的文件)。

DoWork線程的進度對話框中,我還檢查輸出文件是否已經存在並詢問用戶是覆蓋每個文件還是跳過輸出。我用Ookii.Dialogs.Wpf.TaskDialog的ShowDialog(本)一個「任務對話框用命令鏈接」(貌似this),並詢問用戶的覆蓋問題 - 除非該操作系統不支持它,我回退到正常MessageBox該問題適用於消息框以及)。

的問題,當我的應用程序找到現有的文件就在進度對話框的DoWork的線程的開始發生。當任務對話框出現詢問用戶是否覆蓋時:

預期行爲:任務對話框必須保持在最前。當進度對話框出現時(延遲1s後),它必須出現在任務對話框的後面。

實際行爲:任務對話框不保留在最前面。進度對話框在延遲1秒後出現時),它出現在任務對話框的頂部。

當進度對話框已經可見時,在後續的覆蓋請求中不會發生實際行爲。儘管用戶可以來回切換兩個對話框(不能從任何一個對話框切換到主窗口),但任務對話框在後續對話框的進度對話框頂部正確顯示。

我在尋找這樣的:

  • 最好的解決辦法:使任務對話框上出現的進度模態對話框。如果用戶嘗試切換到進度對話框,則不允許用戶這樣做。
  • 次優:即使進度對話框出現在1秒延遲之後,任務對話框的第一次出現仍保持在最前面。

尋找以下:

  • 設置任務對話框的總是在最上層的標誌。我不希望任務對話框始終顯示在用戶計算機上的每個窗口之上。
  • 在任務對話框出現之前添加延遲。我已經嘗試了Thread.Sleep()即使在一個循環中,它只是掛起了一切的執行,並沒有解決問題。
  • 在顯示任務對話框之前,等待進度對話框出現。可以在理論上工作,除了我沒有找到方法來知道進展對話是否已經出現或沒有。
  • 使對話框無模式。我希望他們都是模態。 (除了我已經嘗試使它們無模式;它並沒有幫助解決問題。)
  • 一個解決方案,該解決方案僅適用於只有的任務對話框。它也必須適用於常規消息框。
+1

解決問題的方法是使用進度對話框的窗口句柄作爲任務對話框的父級。不幸的是,Ookii.Dialogs目前沒有公開該功能(主要是因爲當我編寫這個庫時我沒有辦法得到它;結果是沒有文檔記載)。 – Sven 2012-03-07 04:32:39

+0

@Sven':)'很高興收到你的來信!我可以在我自己的源代碼中使用未記錄的方式來獲取進度對話框的窗口句柄嗎?或者您是否必須在Ookii.Dialogs內部使用它來向我公開該句柄?另外,你想不久之後呢?謝謝! – ADTC 2012-03-07 07:02:57

+0

您需要修改Ookii.Dialogs源代碼。我會考慮進行這些修改。 – Sven 2012-03-07 07:26:57

回答

1

我知道這可能有點晚,但我在我自己的程序中搶先了一個類似的問題,它提醒了我這個問題。 我使用窗口FindWindowEx API函數對任務對話窗口標題屬性查找對話框窗口句柄,然後使用我自己的類來創建一個Iwin32Window,然後可以將其用作消息框或任務對話的父項。 相應代碼如下(VB.NET)

'allows us to use the handle as a window 
    class window 
     Implements IWin32Window 
     private _handle 

     public sub new(handle as intptr) 
      _handle = handle 
     end sub 

     Public ReadOnly Property Handle As System.IntPtr Implements System.Windows.Forms.IWin32Window.Handle 
      Get 
       Return _h 
      End Get 
     End Property 
    end class 

    'Declare the needed DLL import 
    class NativeMethods 
     <DllImport("user32.dll", SetLastError:=True, ThrowOnUnmappableChar:=True, CharSet:=CharSet.Unicode, bestFitMapping:=False)> 
     Public Shared Function FindWindowEx(hwndParent As IntPtr, hwndChildAfter As IntPtr, lpszClass As String, lpszWindow As String) As IntPtr 
     End Function 
    end class 

    'Make sure you've set a window title when you run your task 
    sub runTask() 
     dim myDlg as Ookii.Dialogs.ProgressDialog 
     'Do what you need to here 
     myDlg.WindowTitle = "make sure you set a title" 
    end sub 
    sub myTask(sender as object, e As System.ComponentModel.DoWorkEventArgs) 
     'Checks and balances here 
     if fileExists then 
       'this is the dialog that's running our task 
       Dim dlg As Ookii.Dialogs.ProgressDialog = DirectCast(sender, Ookii.Dialogs.ProgressDialog) 
       'Find the window handle 
       Dim dlgHandle As IntPtr = NativeMethods.FindWindowEx(IntPtr.Zero, IntPtr.Zero, Nothing, dlg.WindowTitle) 
       'make it an Iwin32Window 
       dim dlgWindow as new window(dlgHandle) 
       'That can then be used as a parent for the message box or the task dialog 
       MessageBox.Show(dlgWindow,"The file exists, overwrite?") 
     end if 
    end sub 

我不是真的在評論我的代碼或者讓我解釋明白,所以如果您有什麼事情我會盡力幫助有任何疑問非常好。

+0

也許@Sven可以看看它。謝謝! – ADTC 2012-08-19 09:01:46

+2

@ADTC:這基本上是我已經提出的(除了我使用'IOleWindow'來獲得窗口句柄,這裏比'FindWindowEx'黑客更清潔)。問題是,在WPF中,'MessageBox'這樣的東西不會把'IWin32Window'作爲父類,他們想要一個'Window'。並且不可能爲任何實際上不是WPF窗口的任何東西創建一個Window實例。所以儘管對Windows窗體是可行的,但對於WPF來說這是不可行的,這是由於WPF中的設計問題。 – Sven 2012-08-24 07:19:40

0

今天我已經閱讀了這個問題,併爲我找到了解決方案。嘗試了它的TaskDialog,並且這不起作用。沒有嘗試與其他對話。 我寫了一個DialogControler來處理MVVM。 此DialogControlar有一個名爲'Owner'的屬性,其中包含WPF-MainWindow。 然後我用它來調用(在我的情況下,我一直來自viewmodel中的backgroundthread),並在ShowDialog中設置它。

我的代碼:

using (var dialog = new Ookii.Dialogs.Wpf.TaskDialog()) 
     { 
      dialog.WindowTitle = "My title"; 
      dialog.MainInstruction = "My text"; 
      var okButton = new Ookii.Dialogs.Wpf.TaskDialogButton(Ookii.Dialogs.Wpf.ButtonType.Ok); 
      dialog.Buttons.Add(okButton); 
      Owner.Dispatcher.Invoke(new Action(() => dialog.ShowDialog(Owner))); 

     } 

有了這個,我有一個頂層窗口。

+0

*「這是工作」*是或不是? – ADTC 2014-07-23 13:31:43