WPF依賴屬性學(xué)習(xí)
當(dāng)前位置:點晴教程→知識管理交流
→『 技術(shù)文檔交流 』
概述WPF 依賴屬性(Dependency Property)是 WPF 框架的核心基礎(chǔ)設(shè)施之一,它擴展了傳統(tǒng) .NET 屬性的能力,為 WPF 提供數(shù)據(jù)綁定、動畫、樣式、繼承值、屬性值變更通知等高級功能。 為什么需要設(shè)計依賴屬性? 因為依賴屬性做到了CLR屬性沒做到的一些事情。 列舉幾個場景: 1、數(shù)據(jù)驅(qū)動 UI 的動態(tài)性需要“可計算的值 在 WPF 里,綁定的值、樣式 Setter 的值、觸發(fā)器的值、動畫幀的值,都是事后才知道的,甚至可以在運行時不斷切換來源。 CLR 屬性:值寫死在一個私有字段里,誰最后 set 就留誰。 依賴屬性:屬性系統(tǒng)先查看“當(dāng)前這一幀到底是誰最有發(fā)言權(quán)”,再給出最終值——也就是“值是從外部來的,我只是按優(yōu)先級算一算”的依賴計算。 2、大規(guī)模對象樹的內(nèi)存壓力要求“默認值共享 WPF 的控件樹隨隨便便成千上萬實例,如果每個 Button 都把 FontSize = 11 存一份 double,內(nèi)存就爆炸了。 依賴屬性把“默認值”壓縮到一個靜態(tài)全局哈希表里,沒顯式設(shè)置的實例,直接查表用同一份值。 3、樣式 / 動畫 / 綁定 / 繼承 / 觸發(fā)器 / 資源多路輸入需要統(tǒng)一的“優(yōu)先級規(guī)則 同一個 Background,可以是:本地值(紅),主題樣式(藍),動畫(綠),觸發(fā)器(黃)…… 傳統(tǒng)屬性里誰最后 set 誰贏,根本無法表達這種“多源頭分時復(fù)用”的復(fù)雜策略。 4、跨父子樹的“屬性值繼承 典型例子:FontSize 設(shè)到 Window 上,所有子孫 TextBlock 直接復(fù)用該值,但中途隨時可以用樣式或本地值覆蓋。 傳統(tǒng)字段存儲實現(xiàn):父級改一次就要遞歸遍歷整棵樹; 依賴屬性:子元素在取值時惰性向上詢問,邏輯/性能都優(yōu)雅。 學(xué)習(xí)依賴屬性在創(chuàng)建自定義的時候,創(chuàng)建一個依賴屬性的示例如下所示:
首先來看看命名,一個CLR屬性是Value,依賴屬性是ValueProperty,這是一種命名約定,可以很容易將這兩個東西關(guān)聯(lián)起來。 依賴屬性都是通過
OnValueChanged是變更回調(diào):
作用:值真正改變后通知控件更新 UI。 e 中包含舊值 e.OldValue 與新值 e.NewValue,可進一步比較差異。 生命周期小結(jié)(一個賦值的全過程) 代碼 / 綁定 / 動畫嘗試改變 Value。 WPF 調(diào)用 CoerceValue 讓控件有機會矯正值。 如果矯正后的值與當(dāng)前存儲值相同,流程結(jié)束;否則進入下一步。 觸發(fā) OnValueChanged → 更新UI。 因為是 BindsTwoWayByDefault,若存在綁定的源(ViewModel),其對應(yīng)屬性也會被同步。 現(xiàn)在大概了解了依賴屬性的設(shè)計,你可能也聽說過“附加屬性”與“繼承屬性”。 其實官方并沒有“繼承屬性”這個稱謂,繼承屬性只是將依賴屬性設(shè)置成可繼承罷了。 要想更好地理解依賴屬性的概念,一個很好的方式就是去看WPF的源碼,看看在源碼中是如何使用的,現(xiàn)在就讓我們一起去源碼中找找看吧!! 先來看看普通的依賴屬性定義: 目前我們接觸到了
這里官方源碼將按鈕是否按下這個屬性設(shè)置為了只讀依賴屬性,為什么官方是這樣做的呢? 想象一下一個按鈕的 如果你把它做成一個普通的可以隨意讀寫的屬性:
那么任何代碼都可以修改它,這會破壞按鈕的內(nèi)在邏輯和行為一致性。 如果你把它做成一個普通的只讀屬性:
雖然外部代碼不能修改了,但這樣做有幾個缺點: 不支持 WPF 高級功能:它不再是一個依賴屬性,因此無法享受數(shù)據(jù)綁定、樣式、動畫、屬性值繼承等 WPF 的核心特性。比如,你無法在 XAML 中寫一個 Trigger 來在 IsPressed 為 true 時改變按鈕的背景色。 缺少變更通知:如果 _isPressed 的值改變了,WPF 的其他部分(比如 UI 渲染系統(tǒng))不會自動知道。你需要手動實現(xiàn) INotifyPropertyChanged 接口,這額外增加了復(fù)雜性。 為了解決上述問題,WPF 引入了“只讀依賴屬性” (Read-Only Dependency Property) 。這種屬性擁有兩全其美的優(yōu)勢: 對外是只讀的:保護了屬性的完整性,防止外部代碼隨意篡改。 內(nèi)部是可讀寫的:屬性的“所有者”可以在特定邏輯下修改其值。 擁有依賴屬性的全部特性:支持數(shù)據(jù)綁定、樣式、動畫、觸發(fā)器等。 再來看看附加依賴屬性: Grid.Row是一個很經(jīng)典的附加依賴屬性。 注冊附加依賴屬性使用的是 附加屬性必須提供靜態(tài)的 在WPF中一個很經(jīng)典的可繼承依賴屬性的例子就是 使用了 這個枚舉類有以下幾個選項:
現(xiàn)在只是差不多了解了WPF中的依賴屬性的一些概念與使用,要想真正明白依賴屬性的設(shè)計與實現(xiàn),還得多研究研究源碼。 轉(zhuǎn)自https://www.cnblogs.com/mingupupu/p/19074134 該文章在 2025/9/5 8:49:29 編輯過 |
關(guān)鍵字查詢
相關(guān)文章
正在查詢... |