【.net 深呼吸】WPF 中的父子窗口
與 WinForm 不同,WPF 並沒有 MDI 窗口,但 WPF 的窗口之間是可以存在“父子”關系的。
我們會發現,Window 類公開了一個屬性叫 Owner,這個屬性是可讀可寫的,從名字上我們也能猜到,應該是用來設置窗口的父子關系的。這個屬性看起來不難用,只要賦個窗口實例即可,而真正的難點是你得搞清楚“誰是誰的父窗口”,“誰是誰的子窗口”,一旦你搞混了,有可能會應用程序帶來一些小麻煩。
這個問題是一位妹子問我的,不然怎麽說女孩子特別細心呢,這個小玩意兒估計很多時候我們都不會註意到。
下面,老周給大夥兒弄個示例,我們還是“有理有據”,用實際例子來看看父窗口與子窗口之間的關系變化會有啥不同。
第一步,我們準備好主窗口,通常創建 WPF 項目時,項目模板會生成一個主窗口——MainWindow,我們就用它吧。
<Window x:Class="MyDemo.MainWindow" …… mc:Ignorable="d" Title="父窗口" Height="350" Width="525"> <StackPanel Margin="20"> <TextBlock Margin="0,12,0,100" Text="主窗口"FontSize="40" FontFamily="楷體" HorizontalAlignment="Center"/> <Button Content="點擊報名火星單程遊" HorizontalAlignment="Center" Padding="150,15" Click="OnClick"/> </StackPanel> </Window>
註意那個按鈕,後面有用,點擊它可以打開另一個窗口。
第二步,再新建一個 WPF 窗口,XAML 如下。
<Window x:Class="MyDemo.AddNewWindow"…… mc:Ignorable="d" Title="報名" Height="300" Width="300"> <Grid> <Button Content="關閉" VerticalAlignment="Bottom" HorizontalAlignment="Center" Padding="100,10" Click="OnClick"/> </Grid> </Window>
那個“關閉”按鈕沒啥特殊功能,只是用來關閉窗口,代碼如下。
private void OnClick(object sender, RoutedEventArgs e) { Close(); }
第三步,回到主窗口,剛剛老周提醒過,主窗口上那個 Button 控件,現在要用上了,我們處理一下它的單擊事件。
private void OnClick(object sender, RoutedEventArgs e) { AddNewWindow w2 = new AddNewWindow(); w2.Show(); this.Owner = w2; }
對一個窗口來說,必須顯示以後,才能操作 Owner 屬性,為了安全保險,大家可以在窗口顯示後再去思考誰是誰的 Owner。
現在我們來運行一下。打開新窗口時是這樣的。
然後,切換到其他窗口,再切換回來,你會看到,此時就算新窗口處於激活狀態,主窗口始終擋在新窗口前。
而且,你還會發現,把主窗口關了程序不會退出,但把新窗口關了程序就會退出。那是因為現在 w2 才是父窗口,而 MainWindow 成了子窗口。
現在我們把代碼改一下。
AddNewWindow w2 = new AddNewWindow(); w2.Show(); //this.Owner = w2; w2.Owner = this;
看好了,這一次是 MainWindow 作為父窗口,w2 作為子窗口。這樣的邏輯才符合我們的要求,當初的預期就是,MainWindow 窗口上打開新窗口,並且當進行了窗口切換後再次回到應用程序時,應當讓新打開的窗口處於活動狀態。
再次運行,此時,你會看到,新窗口始終會擋在主窗口前面。
好了,今天的內容就差不多了,還是那句話,你要弄清楚誰是誰的父窗口。給大家一句萬能口訣:Owner 屬性所引用的窗口就會成為父窗口。
【.net 深呼吸】WPF 中的父子窗口