wpf 實現窗口點擊關閉按鈕時 ??隱藏?? 而不是真正關閉,并且只有當 ??父窗口關閉時才真正退出?? 、父子窗口順序控制與資源安全釋放?

文章目錄

    • 實現方法
      • **方法 :重寫 `OnClosing` 方法**
        • **子窗口(SettingView)代碼**
        • **父窗口(MainWindow)代碼**
      • **關鍵點**
      • **適用場景**
    • 為什么if (Owner == null || !Owner.IsLoaded)能夠判斷父窗口已經關閉
      • **1. `Owner == null` 檢查**
      • **2. `!Owner.IsLoaded` 檢查**
      • **為什么 `Owner` 不會自動置 `null`?**
      • **正確的判斷邏輯**
      • **特殊情況**
      • **總結**
    • 應用程序退出會自動關閉所有窗口嗎,怎么知道先關父窗口還是先關子窗口呢
    • **1. 應用程序退出時,所有窗口會自動關閉嗎?**
    • **2. 如何知道先關閉父窗口還是子窗口?**
      • **驗證示例**
    • **3. 如何控制關閉順序?**
      • **方法 1:手動管理關閉順序**
      • **方法 2:阻止子窗口自動關閉**
    • **4. 關鍵總結**
    • **5. 最佳實踐**

實現方法

在 WPF 中,如果希望窗口點擊關閉按鈕時 隱藏 而不是真正關閉,并且只有當 父窗口關閉時才真正退出,可以通過以下方式實現:


方法 :重寫 OnClosing 方法

在子窗口(SettingView)中重寫 OnClosing,判斷是否由父窗口觸發關閉,如果不是則取消關閉并隱藏窗口。

子窗口(SettingView)代碼
public partial class SettingView : Window
{public SettingView(){InitializeComponent();}protected override void OnClosing(CancelEventArgs e){// 如果父窗口正在關閉,則允許子窗口關閉if (Owner == null || !Owner.IsLoaded){base.OnClosing(e);return;}// 否則隱藏窗口,并取消關閉操作e.Cancel = true;this.Hide();}
}
父窗口(MainWindow)代碼
public partial class MainWindow : Window
{private SettingView _settingView;public MainWindow(){InitializeComponent();_settingView = new SettingView { Owner = this };}private void ShowSettingView_Click(object sender, RoutedEventArgs e){_settingView.Show(); // 顯示窗口(如果已隱藏)}protected override void OnClosed(EventArgs e){base.OnClosed(e);_settingView.Close(); // 父窗口關閉時,真正關閉子窗口}
}

關鍵點

  1. Owner 屬性:子窗口必須設置 Owner = this(父窗口),否則無法判斷父窗口是否關閉。
  2. IsLoaded 檢查:確保父窗口仍然存在,避免 NullReferenceException
  3. Hide() 代替 Close():點擊關閉按鈕時隱藏窗口,而不是銷毀。
  4. 父窗口關閉時真正關閉子窗口:在父窗口的 OnClosed 中調用 Close()

適用場景

  • 設置窗口:點擊關閉按鈕時隱藏,下次打開時恢復狀態。
  • 工具窗口:不希望頻繁創建和銷毀窗口,提高性能。
  • 模態對話框:保持數據狀態,直到父窗口關閉。

為什么if (Owner == null || !Owner.IsLoaded)能夠判斷父窗口已經關閉

1. Owner == null 檢查

  • Owner 是 WPF 窗口的一個屬性,表示當前窗口的父窗口。
  • 如果 父窗口從未被設置(即 Owner 從未賦值),則 Owner == nulltrue
  • 如果 父窗口已被關閉,WPF 不會自動將 Owner 設為 null,所以 Owner == null 通常不會為 true(除非手動置空)。

結論Owner == null 主要用于檢測 是否從未設置父窗口,而不是檢測父窗口是否關閉。


2. !Owner.IsLoaded 檢查

  • IsLoaded 是 WPF 窗口的一個屬性,表示窗口是否已經加載并顯示。
  • 父窗口關閉時,它的 IsLoaded 會變為 false(即使 Owner 仍然指向它)。
  • 因此,!Owner.IsLoaded 可以判斷 父窗口是否已關閉

結論!Owner.IsLoaded 是檢測父窗口是否關閉的關鍵條件。


為什么 Owner 不會自動置 null

  • WPF 的 Owner 屬性是一個 弱引用(Weak Reference),它不會阻止垃圾回收(GC)。
  • 父窗口關閉后Owner 仍然會保留對它的引用(只是 IsLoaded 變為 false)。
  • 如果父窗口被垃圾回收,Owner 也不會自動變成 null(除非手動賦值 Owner = null)。

正確的判斷邏輯

if (Owner == null || !Owner.IsLoaded)
{// 情況1:從未設置父窗口(Owner == null)// 情況2:父窗口已關閉(!Owner.IsLoaded)base.OnClosing(e); // 允許關閉
}
else
{e.Cancel = true;  // 取消關閉this.Hide();      // 隱藏窗口
}

特殊情況

  1. 如果父窗口從未設置(Owner == null
    • 子窗口會直接關閉(因為沒有父窗口需要等待)。
  2. 如果父窗口已關閉(!Owner.IsLoaded
    • 子窗口也會關閉(因為父窗口已經不存在了)。
  3. 如果父窗口仍然存在(Owner != null && Owner.IsLoaded
    • 子窗口會隱藏(Hide()),而不是關閉。

總結

條件含義
Owner == null從未設置父窗口
!Owner.IsLoaded父窗口已關閉(或未加載)
!Owner.IsVisible父窗口不可見(可能是最小化或隱藏)
!Owner.IsActive父窗口未激活(不是當前焦點窗口)

if (Owner == null || !Owner.IsLoaded) 是一個 合理且安全 的方式來判斷父窗口是否關閉。 ?


應用程序退出會自動關閉所有窗口嗎,怎么知道先關父窗口還是先關子窗口呢

在 WPF 中,窗口關閉順序和應用程序退出的行為取決于 窗口的所有權關系(Owner關閉邏輯。以下是關鍵問題的解答:


1. 應用程序退出時,所有窗口會自動關閉嗎?

? 是的,但取決于關閉方式:

  • 正常關閉(Application.Current.Shutdown()
    所有窗口(包括隱藏的)會按 反向順序 關閉(子窗口先關閉,父窗口后關閉)。
  • 強制關閉(Environment.Exit(0) 或進程終止)
    所有窗口 立即銷毀,不觸發 Closing 事件。

2. 如何知道先關閉父窗口還是子窗口?

WPF 的窗口關閉順序遵循 從子到父 的規則:

  1. 子窗口先關閉(如果設置了 Owner)。
  2. 父窗口后關閉

驗證示例

// 父窗口(MainWindow)
public partial class MainWindow : Window
{public MainWindow(){InitializeComponent();var childWindow = new ChildWindow { Owner = this };childWindow.Show();}protected override void OnClosing(CancelEventArgs e){Console.WriteLine("父窗口正在關閉");base.OnClosing(e);}
}// 子窗口(ChildWindow)
public partial class ChildWindow : Window
{protected override void OnClosing(CancelEventArgs e){Console.WriteLine("子窗口正在關閉");base.OnClosing(e);}
}

輸出

子窗口正在關閉
父窗口正在關閉

👉 結論:子窗口先關閉,父窗口后關閉。


3. 如何控制關閉順序?

方法 1:手動管理關閉順序

如果希望 父窗口關閉時,子窗口才關閉(而不是相反),可以:

// 父窗口(MainWindow)
protected override void OnClosing(CancelEventArgs e)
{// 先關閉所有子窗口foreach (Window window in OwnedWindows){window.Close();}base.OnClosing(e);
}

方法 2:阻止子窗口自動關閉

如果希望 子窗口在父窗口關閉時保持存活(例如隱藏而非關閉):

// 子窗口(ChildWindow)
protected override void OnClosing(CancelEventArgs e)
{if (Owner != null && Owner.IsVisible){e.Cancel = true;  // 取消關閉this.Hide();      // 隱藏窗口}else{base.OnClosing(e); // 父窗口已關閉,允許子窗口關閉}
}

4. 關鍵總結

行為說明
默認關閉順序子窗口 → 父窗口(反向依賴順序)
Owner 的作用決定窗口的父子關系,影響關閉順序
Application.Current.Shutdown()觸發所有窗口按順序關閉
Environment.Exit(0)強制終止,不觸發 Closing 事件
隱藏窗口是否影響關閉?隱藏的窗口仍然會被關閉,除非手動取消 Closing

5. 最佳實踐

  • 如果子窗口需要存活(如工具窗口):
    • Closing 事件中 Hide() + e.Cancel = true
  • 如果子窗口必須隨父窗口關閉
    • 讓 WPF 自動處理(默認行為)。
  • 如果需要自定義關閉順序
    • 在父窗口 OnClosing 中手動關閉子窗口。

這樣就能精準控制 WPF 窗口的關閉邏輯! 🚀

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/89362.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/89362.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/89362.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

硬件設計學習DAY4——電源完整性設計:從概念到實戰

每日更新教程,評論區答疑解惑,小白也能變大神!" 目錄 一.電源完整性 1.1電源完整性的核心概念 1.2電源完整性的三個關鍵目標 1.3地彈現象的通俗解釋 1.4總結要點 二.電源分配網絡(PDN)的作用 電源與GND網絡…

QT跨平臺應用程序開發框架(8)—— 多元素控件

目錄 一,關于多元素控件 二,QListWidget 2.1 主要方法 2.2 實現新增刪除 三,Table Widget 3.1 主要方法 3.2 代碼演示 四,Tree Widget 4.1 主要方法 4.2 代碼演示 一,關于多元素控件 多元素控件就是一個控件里面包含了…

【React Native】環境變量和封裝 fetch

環境變量和封裝fetch 環境變量 一般做開發,都會將接口地址配置到環境變量里。在Expo建的項目里,也可以使用環境變量。 在項目根目錄新建一個.env文件,里面添加上: EXPO_PUBLIC_API_URLhttp://localhost:3000如果你用手機真機等…

Linux 基礎命令詳解:從入門到實踐(1)

Linux 基礎命令詳解:從入門到實踐(1) 前言 在 Linux 操作系統中,命令行是高效管理系統、操作文件的核心工具。無論是開發者、運維工程師還是Linux愛好者,掌握基礎命令都是入門的第一步。本文將圍繞Linux命令的結構和常…

基于 SpringBoot+VueJS 的私人牙科診所管理系統設計與實現

基于 SpringBootVueJS 的私人牙科診所管理系統設計與實現摘要隨著人們對口腔健康重視程度的不斷提高,私人牙科診所的數量日益增多,對診所管理的信息化需求也越來越迫切。本文設計并實現了一個基于 SpringBoot 和 VueJS 的私人牙科診所管理系統&#xff0…

華為云Flexus+DeepSeek征文|體驗華為云ModelArts快速搭建Dify-LLM應用開發平臺并創建天氣預報大模型

華為云FlexusDeepSeek征文|體驗華為云ModelArts快速搭建Dify-LLM應用開發平臺并創建天氣預報大模型 什么是華為云ModelArts 華為云ModelArts ModelArts是華為云提供的全流程AI開發平臺,覆蓋從數據準備到模型部署的全生命周期管理,幫助企業和開…

Mysql系列--0、數據庫基礎

目錄 一、概念 1.1什么是數據庫 1.2什么是mysql 1.3登錄mysql 1.4主流數據庫 二、Mysql與數據庫 三、Mysql架構 四、SQL分類 五、存儲引擎 5.1概念 5.2查看引擎 5.3存儲引擎對比 一、概念 1.1什么是數據庫 由于文件保存數據存在文件的安全性問題 文件不利于數據查詢和管理…

深度學習和神經網絡的介紹

一.前言本期不涉及任何代碼,本專欄剛開始和大家介紹了一下機器學習,而本期就是大家介紹一下深度學習還有神經網絡,作為一個了解就好。二.深度學習2.1 什么是深度學習?在介紹深度學習之前,我們先看下??智能&#xff0…

AI驅動的軟件工程(下):AI輔助的質檢與交付

📚 系列文章導航 AI驅動的軟件工程(上):人機協同的設計與建模 AI驅動的軟件工程(中):文檔驅動的編碼與執行 AI驅動的軟件工程(下):AI輔助的質檢與交付 大家好…

【WRFDA實操第一期】服務器中安裝 WRFPLUS 和 WRFDA

目錄在服務器上下載并解壓 WRF v4.6.1編譯 WRFDA 及相關庫安裝和配置所需庫安裝 WRFPLUS 和 WRFDA 以運行 4DVAR 數據同化一、安裝 WRFPLUS(適用于 WRF v4.0 及以上版本)二、安裝 WRFDA(用于 4DVAR)WRFDA 和 WRFPLUS 的安裝說明另…

【機器學習【6】】數據理解:數據導入、數據審查與數據可視化方法論

文章目錄一、機器學習數據導入1、 Pandas:機器學習數據導入的最佳選擇2、與其他方法的差異二、機器學習數據理解的系統化方法論1、數據審查方法論:六維數據畫像技術維度1:數據結構審查維度2:數據質量檢查維度3:目標變量…

AI煉丹日志-30-新發布【1T 萬億】參數量大模型!Kimi?K2開源大模型解讀與實踐

點一下關注吧!!!非常感謝!!持續更新!!! 🚀 AI篇持續更新中!(長期更新) AI煉丹日志-29 - 字節跳動 DeerFlow 深度研究框斜體樣式架 私…

如何關閉Elasticsearch的安全認證的解決方法

在Elasticsearch 中,啟動之后,需要輸入用戶名和密碼,才可以訪問,在測試環境中,很不方便,本章教程,主要介紹如何關閉Elasticsearch 的安全認證。在 Elasticsearch 8.x / 9.x 中,默認是…

day051-ansible循環、判斷與jinja2模板

文章目錄0. 老男孩思想-男女性需求差異1. 手動指定客戶機密碼2. 批量更新主機名2.1 hostname模塊2.2 添加主機清單變量2.3 編寫批量修改主機名劇本2.4 修改hosts文件2.5 分發hosts文件劇本3. ansible的并行進程數4. 分組設置主機密碼-主機清單分組變量5. 案例:ansib…

大模型安全建設:破誤區、識風險、筑防線20250714

🔐 大模型安全建設:破誤區、識風險、筑防線作者:Narutolxy|編輯時間:2025年7月在負責公司 AI 產品落地的過程中,一度以為只要選用主流開源大模型,前面加一層“敏感詞提示詞過濾”,就…

fastadmin中ajax彈窗修改文字為英文

需要把上圖的中文改為 切換語言自動切換成英文找到這個文件public/assets/js/backend.js找到如下圖部分 // //點擊包含.btn-ajax的元素時發送Ajax請求 原頁面// $(document).on(click, .btn-ajax,.ajaxit, function (e) {// var that this;// var options $.exte…

大型語言模型(LLM)的技術面試題

大型語言模型(LLM)的技術面試題 目錄 大型語言模型(LLM)的技術面試題 一、提示校準:減輕提示學習中的偏見 二、矢量存儲的適用場景 三、模型與人類價值觀對齊的技術 四、RLHF中的Reward Hacking 五、微調效果的關鍵影響因素:預訓練模型架構與大小 六、Transformer自注意力…

數字IC后端培訓教程之數字IC后端項目典型問題解析

今天給大家分享下最近幾個典型的數字后端項目案例,希望對大家的學習和工作有所幫助。 數字IC后端培訓教程之數字后端項目典型項目案例解析 Q1:星主,有啥辦法可以看到refinePlace或者ecoPlace都動到了那些inst嗎,log里只會有mean和max move&…

網絡(數據庫1)

常用數據庫: 1.關系型數據庫: 將復雜的數據結構簡化為二維表格形式 大型:0racle、DB2 中型:MySq1、sQLServer 小型:Sqlite 2.非關系型數據庫以鍵值對存儲,且結構不固定。//JSON Redis MongoDB數據存儲:變量、數組、鏈表 內存 &…

6.刪除-demo

在連接數據庫的基礎上deleteResult, err : db.Exec("DELETE FROM user0 WHERE id ?", 1)package main//刪除-demoimport ("database/sql""fmt"_ "github.com/go-sql-driver/mysql""log" )func main() {db, err : sql.Open…