在 Windows 窗體中載入與顯示事件
希望我只是遺漏了一些明顯的東西,但我試圖弄清楚Windows Forms中的 Load 和 Shown 事件之間的差異。
傳統上,我只使用了 Load(或者實際上是 OnLoad,因為我認為重寫一個方法比依賴設計器自己連接一個事件更乾淨),因為它在所有版本的 .NET 中都可用。.NET 2.0 引入了 Shown 事件。
現在,如果您在 MSDN 文件中查看這些描述(“載入:在第一次顯示表單之前發生。”,“顯示:在第一次顯示表單時發生。”)聽起來像 Load 事件應該發生,然後表單應該變得可見,然後應該發生 Shown 事件;兩者的結合使您可以在表格可見之前和之後執行一些任務。有道理,對吧?
然而,實驗表明 Shown 事件總是發生在Load 事件之前,每當我嘗試它時(並且兩者都發生在表單變得可見之前)。然而,每當我發現一個頁面討論這些事件的觸發順序時,他們總是列出首先觸發的 Load 事件。
我只是瘋了,還是我錯過了什麼?(如果它們確實幾乎同時發生,那麼為什麼首先添加 Shown 事件?)
(我目前在顯示表單之前和之後做某事的解決方案是將 OnLoad 用於“顯示前”的內容,並為“顯示後”的內容啟動一個短時間的一次性計時器。它工作正常且可靠,但是這有點難看,我希望有一個更清潔的解決方案。但看起來 Shown 事件不是它。)
避免使用 MessageBox.Show() 來調試它。它泵出一個消息循環,擾亂了正常的事件流。Load事件由 Windows 發送 WM_SHOWWINDOW 消息觸發,就在視窗變得可見之前。沒有關於“您的視窗現在已完全顯示”的 Windows 通知,因此 WF 設計者想出了一個技巧來生成Shown事件。他們使用 Control.BeginInvoke(),確保一旦程序再次空閒並重新進入消息循環,就會呼叫 OnShown() 方法。
這個技巧還有很多其他用途,特別是當您必須延遲執行由事件啟動的程式碼時。但是,在您的情況下,它會因為您使用 MessageBox.Show() 而分崩離析。它的消息循環調度使用 BeginInvoke() 註冊的委託,導致 Shown 事件在視窗顯示之前執行。
除了 MessageBox 之外,還有許多其他方法可以獲取診斷資訊。Debug.Print() 和 Console.WriteLine() 很方便,它們的輸出進入Visual Studio 輸出視窗,而不會對正常的事件觸發序列產生任何不利影響。一個簡單的斷點也可以創造奇蹟。