WPF 採用全新的架構模型,區別於 WinForms 的訊息迴圈與單一視覺樹。本文系統梳理 Application/Window 生命週期、Dispatcher 線程調度機制、類別繼承體系、邏輯樹與視覺樹雙樹模型,並提供完整事件追蹤代碼驗證,幫你建立扎實的 WPF 核心心智模型。
App.xaml 設 StartupUri,編譯器生成 Main() 自動啟動。Main() 建立 Application 實例,呼叫 Run(Window)、Run()(需先 MainWindow=win; win.Show())、或設 StartupUri。ShutdownMode:OnLastWindowClose(預設)、OnMainWindowClose、OnExplicitShutdown。可在 XAML 或 Run() 前設定。
Startup、Exit、DispatcherUnhandledException(UI 線程未處理例外)、SessionEnding(系統登出/關機)、導航相關事件(Navigating、Navigated、LoadCompleted 等)。
Show() 非模態、ShowDialog() 模態。Close() 關閉並釋放資源。Closing (CancelEventArgs) 可取消、Closed 已關閉。Activated/Deactivated 追蹤焦點獲取/失去。Activate() 程式化激活。
SourceInitialized Loaded ContentRendered Activated ... (用戶切換視窗) Deactivated Activated ... (用戶關閉視窗) Closing (可 e.Cancel=true 阻止) Closed Unloaded
代碼驗證:在建構子訂閱所有事件,Debug.WriteLine 輸出順序。
WPF 啟動建立兩個線程:UI 線程(渲染/輸入/佈局)與渲染線程(GPU 合成,通常隱藏)。所有 DispatcherObject 具有線程親和性,僅創建線程可直接存取。
// 同步封送(阻塞呼叫線程)
Dispatcher.Invoke(Action, DispatcherPriority);
// 非同步封送(立即返回)
Dispatcher.BeginInvoke(Action, DispatcherPriority);
// 檢查是否需封送
if (!CheckAccess()) Dispatcher.Invoke(...);
Application.Current.Dispatcher 取得全域 UI Dispatcher。DispatcherPriority.Normal 適用多數場景;Render 級別用於動畫幀回調。
System.Object
└ System.Windows.Threading.DispatcherObject // 線程親和性、Dispatcher 存取
└ System.Windows.DependencyObject // 依賴屬性系統
└ System.Windows.Media.Visual // 渲染基元、座標轉換、命中測試
└ System.Windows.UIElement // 核心:輸入、佈局、焦點、事件路由
└ System.Windows.FrameworkElement // 框架層:樣式、資料綁定、資源、動畫、工具提示
├ System.Windows.Controls.Control // ControlTemplate 外觀
│ ├ ContentControl // 單一內容
│ ├ ItemsControl // 項目集合
│ └ ...
├ System.Windows.Controls.Panel // 佈局容器基類
├ System.Windows.Controls.Decorator // 單一子元素裝飾
└ System.Windows.Shapes.Shape // 幾何圖形
其他重要類別:Image、MediaElement、ContentPresenter(模板內容宿主)。
對應 XAML 元素巢狀結構。例:Window → StackPanel → Label → "Hello"。字串內容也是葉節點。支援:資源查找、屬性值繼承、事件路由(Bubbling/Tunneling)。
邏輯樹節點展開為渲染基元。例:Label → Border → ContentPresenter → TextBlock → TextRun。僅 Visual/Visual3D 衍生類出現。支援:命中測試、座標轉換、邊界計算、模板實例化視覺化。
void PrintLogicalTree(int depth, object obj) {
Debug.WriteLine(new string(' ', depth) + obj);
if (!(obj is DependencyObject)) return;
foreach (var child in LogicalTreeHelper.GetChildren((DependencyObject)obj))
PrintLogicalTree(depth+1, child);
}
void PrintVisualTree(int depth, DependencyObject obj) {
Debug.WriteLine(new string(' ', depth) + obj);
for (int i=0; i
邏輯樹:4 層(Window/StackPanel/Label/String)。視覺樹:10+ 層(含 Chrome、Border、AdornerLayer、ContentPresenter 等)。
XAML 編譯為 BAML (Binary Application Markup Language) 嵌入組件資源。運行時 Application.LoadComponent 解析 BAML 建立物件樹。InitializeComponent 即此過程。理解此機制有助於動態載入、主題切換、原始碼保護。
掌握 Application/Window 生命週期、Dispatcher 線程調度、雙樹模型、類別繼承體系,是驅動 WPF 進階開發(自訂控件、效能調優、架構設計、異常診斷)的基石。建議動手跑通事件追蹤代碼,親眼見證雙樹差異,內化為直覺。