如何應用決定哪個窗口將導致關閉該程序?
默認情況下,Application
類將退出Run()
方法(因此這裏的全過程)時,所有打開的窗口已經關閉。根據你的代碼示例,似乎有一個皺紋:Application
類不考慮它自己創建之前打開的任何窗口。如果你不告訴它任何窗口(即通過傳遞參考Run()
方法),那麼任何窗口關閉都會導致Run()
方法退出,因爲Application
類確實是看到窗口的關閉,但認爲在這個過程中沒有窗戶。
是該窗口中的 「主」 窗口?
默認情況下,「主」窗口是要在AppDomain
中實例化的第一個窗口。您可以隨時通過設置Application
對象的MainWindow
屬性來覆蓋此屬性。
當然,如上面所討論的,Application
對象沒有辦法看到被創建之前它本身創建的窗口。一個例外:如果您將窗口傳遞給Run()
方法,即使該窗口是在Application
對象之前創建的,也可以成爲MainWindow
。如果所有的窗口都是在Application
之前創建的,並且您沒有將這些窗口的引用傳遞給Run()
方法,那麼根本沒有主窗口。
如果要確定性地指定單個窗口以在窗口關閉時導致進程退出,則有一個選項是將其傳遞給Application.Run()
方法。例如:
class Program
{
public static int WindowCounter = 0;
private static Window _firstWindow;
[STAThread]
public static void Main()
{
ShowBeforeApplicationCreation();
}
public static void ShowBeforeApplicationCreation()
{
ShowWindow();
ShowWindow();
ShowWindow();
var app = new Application();
app.Run(_firstWindow);
}
public static void ShowWindow()
{
var window = new Window { Title = string.Format("Title{0}", WindowCounter++) };
window.Show();
_firstWindow = _firstWindow ?? window;
}
}
也就是說,默認Application.ShutdownMode
值爲ShutdownMode.OnLastWindowClose
,所以沒有做別的事情,程序應該不關閉,直到最後一個窗口被關閉。這只是因爲類似乎沒有注意到在實例化之前發生的窗口打開(它顯然會對窗口的實際創建做出反應,而不是在啓動時搜索打開的窗口的過程)。
很明顯,在Application.Run()
之前創建窗口被稱爲混淆方法;它似乎認爲如果任何一個窗戶關閉,窗戶仍然沒有開放。如果你傳遞給其中一個窗口的引用,它將不會返回到該窗口關閉之前,該窗口是它「知道」的唯一窗口;任何其他窗口的關閉都會被忽略,因爲它知道的一個窗口仍然是打開的。 (在我的測試中,程序不會退出,直到所有的窗口關閉,它們都在Application
對象之後創建,這與Application
類正確註釋的上述想法一致任何窗口創建和/或顯示後它自己創建)。
恕我直言,最好的辦法是不要混淆的方法。它無法正確處理在Application
對象創建之前顯示的窗口。所以,不要這樣做。確保在創建Application
之後,纔會創建全部。如果您關閉的具體行爲與默認的ShutdownMode.OnLastWindowClose
行爲不同,那麼這應該很簡單,可以實現。
這可能是因爲剛剛ShutdownMode
屬性設置爲別的東西一樣簡單。例如,ShutdownMode.OnMainWindowClose
。在這種情況下,您當然需要確保某個窗口是主窗口,否則該進程將不會退出。您可以明確,甚至通過傳遞窗口參考Run()
方法在創建了使用默認行爲做到這一點(即創建主窗口的第一個窗口,但Application
對象被創建之後),通過設置MainWindow
財產Application
對象之前的所有窗口。
讓我們來定義關閉過程中OwningWindow(希望這個名字是不是在這方面載)窗口。我怎樣才能確保顯示的第一個窗口是OwningWindow?
從上面的討論中,你也許可以自己回答這個問題。 :)
首先, 「擁有窗口」 實際上是MainWindow
。但是,默認情況下,Application.Run()
方法僅在所有窗口(它已知)已關閉時纔會返回。只有通過隱藏Application
方法中的一些窗口,才能看到某個「擁有窗口」負責關閉程序(在默認的ShutdownMode
方案中)。實際上,如果你想要的只是在某些特定的窗口本身關閉時關閉程序,那麼正確的方法是確保MainWindow
設置正確,並且已將Application.ShutdownMode
設置爲值爲ShutdownMode.OnMainWindowClose
。這樣一來,你正在使用WPF完全明確一下你想要的確切行爲,它不會有機會搞砸了,即使你做一些怪異像創建Application
對象之前創建一個Window
對象。:)
Ah默認ShutdownMode解釋了爲什麼當我通過窗口它仍然有相同的行爲(當我期望我通過的窗口關閉應用程序退出時)。感謝您的詳細回覆! – user815512
繼續這個主題,讓我們說,作爲我的應用程序啓動的一部分,我想顯示一個窗口,然後在關閉之後顯示另一個窗口。我可以通過不同的窗口調用app.Run()兩次來做到這一點嗎?或者是一些涉及Application類的狀態,將禁止這個? – user815512
@ user815512:我不知道我的頭頂。我希望你能夠多次調用'Run()'。但是我也認爲如果這是你的場景,你最好將'ShutdownMode'設置爲'OnExplicitShutdown',這樣你的代碼就可以完全控制。或者,使用'OnMainWindowClose',只要您在關閉第一個窗口並設置MainWindow屬性之前創建第二個窗口,則關閉第一個窗口不應導致應用程序退出。基本上:爲什麼要問麻煩? WPF允許你完全控制關閉邏輯,所以你也可以。 –