2015-11-17 67 views
2

WPF應用程序類和主窗口初始化

public static int WindowCounter = 0; 

[STAThread] 
public static void Main() 
{ 
    ShowBeforeApplicationCreation(); 
    //ShowAfterApplicationCreation(); 
} 

public static void ShowBeforeApplicationCreation() 
{ 
    ShowWindow(); 
    ShowWindow(); 
    ShowWindow(); 
    var app = new Application(); 
    app.Run(); 
} 

public static void ShowAfterApplicationCreation() 
{ 
    var app = new Application(); 
    ShowWindow(); 
    ShowWindow(); 
    ShowWindow(); 
    app.Run(); 
} 

public static void ShowWindow() 
{ 
    var window = new Window { Title = string.format("Title{0}", WindowCounter++) }; 
    window.Show(); 
} 

如果我運行的代碼所示,我關閉任何它會關閉所有窗口的窗口。如果我切換到註釋掉的部分,關於哪個窗口會導致所有窗口關閉(大部分時間是最後一個窗口)似乎是隨機的。

如何應用決定哪個窗口將導致關閉該程序?

是該窗口中的「主」窗口?

讓我們來定義關閉過程中OwningWindow(希望這個名字是不是在這方面載)窗口。我怎樣才能確保顯示的第一個窗口是OwningWindow?

最後一個問題是我的主要問題。我不想打開其他二級窗口,讓用戶關閉主窗口,並讓進程繼續運行。或者,我是否必須讓窗口的後續窗口成爲OwningWindow的窗口?

回答

1

如何應用決定哪個窗口將導致關閉該程序?

默認情況下,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對象。:)

+0

Ah默認ShutdownMode解釋了爲什麼當我通過窗口它仍然有相同的行爲(當我期望我通過的窗口關閉應用程序退出時)。感謝您的詳細回覆! – user815512

+0

繼續這個主題,讓我們說,作爲我的應用程序啓動的一部分,我想顯示一個窗口,然後在關閉之後顯示另一個窗口。我可以通過不同的窗口調用app.Run()兩次來做到這一點嗎?或者是一些涉及Application類的狀態,將禁止這個? – user815512

+0

@ user815512:我不知道我的頭頂。我希望你能夠多次調用'Run()'。但是我也認爲如果這是你的場景,你最好將'ShutdownMode'設置爲'OnExplicitShutdown',這樣你的代碼就可以完全控制。或者,使用'OnMainWindowClose',只要您在關閉第一個窗口並設置MainWindow屬性之前創建第二個窗口,則關閉第一個窗口不應導致應用程序退出。基本上:爲什麼要問麻煩? WPF允許你完全控制關閉邏輯,所以你也可以。 –

相關問題