【WPF】WPF 自定義控件之依賴屬性

📦 WPF 自定義控件之依賴屬性

在開發 WPF 應用時,自定義控件能幫助我們復用邏輯和樣式,但我很快會遇到一個問題:在控件內部如何支持數據綁定和屬性變更通知?特別是我們繼承自 Control 的時候,已經不能再繼承 BindableBase 了,這就聊聊依賴屬性機制。


🧩 一、為什么使用依賴屬性?

在 MVVM 架構中,我們通常使用 BindableBase 或類似類提供的 INotifyPropertyChanged 實現屬性通知。但當你開發一個自定義控件,比如從 ControlButtonItemsControl 等繼承時:

  • 不能再繼承 BindableBase
  • 控件的屬性需要支持樣式設置、動畫、綁定、默認值等特性。

這時就試試 依賴屬性(DependencyProperty)。畢竟依賴屬性天然支持綁定(只是寫起來畢竟麻煩。。。)

? 依賴屬性的優勢:

  • 支持樣式系統
  • 支持數據綁定
  • 支持動畫(如 Storyboard)
  • 支持屬性值繼承
  • 提供更強大的性能優化(例如內存占用更低)

🛠? 二、如何在自定義控件中定義依賴屬性?

我們以一個自定義控件 ImageMessageControl 為例,它有一個 ImageMessage 屬性,用于顯示一段提示文字。

💡 Step 1:繼承 Control 類

public class ImageMessageControl : Control
{static ImageMessageControl(){DefaultStyleKeyProperty.OverrideMetadata(typeof(ImageMessageControl), new FrameworkPropertyMetadata(typeof(ImageMessageControl)));}public string ImageMessage{get { return (string)GetValue(ImageMessageProperty); }set { SetValue(ImageMessageProperty, value); }}public static readonly DependencyProperty ImageMessageProperty =DependencyProperty.Register(nameof(ImageMessage),typeof(string),typeof(ImageMessageControl),new PropertyMetadata(string.Empty));
}

🧵 三、在模板中綁定依賴屬性

控件模板是通過 Generic.xaml 定義的,我們如何讓模板里的 TextBlock 綁定到這個 ImageMessage 屬性?

有兩種常見方式:

? 方法一:使用 TemplateBinding(簡潔)

<TextBlock Text="{TemplateBinding ImageMessage}" />

? 方法二:使用 Binding + RelativeSource

<TextBlock Text="{Binding Path=ImageMessage, RelativeSource={RelativeSource TemplatedParent}}" />

?? 四、兩種綁定方式的區別

比較項TemplateBindingBinding RelativeSource=TemplatedParent
簡潔性? 簡潔,語法短? 稍顯繁瑣
支持的功能? 不支持轉換器、綁定模式、值轉換器等? 支持所有 Binding 功能
性能? 性能更優(編譯時優化)? 性能略遜
可擴展性? 功能有限? 功能更強大
是否可能失敗少見(依賴于模板綁定)? 更容易出錯

🧨 五、為何 RelativeSource=TemplatedParent 有時綁定失敗?

我今天就遇到了 RelativeSource={RelativeSource TemplatedParent} 綁定不生效的問題,其原因有以下幾個,其實就是上面表格中總結的:
TemplateBinding 在 WPF 中不支持真正的雙向綁定。它的行為是單向的,只能從模板化父元素(應用模板的控件)向模板內部傳遞值。

TemplateBinding 的限制及好處

  1. 單向綁定:默認情況下只支持從模板父元素到模板內部控件的單向綁定
  2. 不支持轉換器:不能像常規綁定那樣使用值轉換器
  3. 輕量級:比常規綁定性能更高,但功能更有限

為什么 TemplateBinding 不支持雙向

TemplateBinding 設計初衷是為了模板中的輕量級綁定場景,主要目的是將控件屬性值應用到其模板中的可視化元素上。雙向綁定需要更復雜的機制,所以被有意限制為單向。

如果您需要雙向綁定功能,請使用 RelativeSource 結合 TemplatedParent 的常規 Binding 語法。

<TextBlock Text="{Binding Path=ImageMessage, RelativeSource={RelativeSource TemplatedParent}}" />

TemplateBinding 和 Binding 綁定源的區別

1 TemplateBinding

單向綁定,只能在控件模板(如ControlTemplate或DataTemplate)中使用。
綁定源固定為模板的目標控件(即應用該模板的控件實例)。
例如,在Button的模板中使用TemplateBinding Content,綁定的是該Button自身的Content屬性。

2 Binding

可在任何地方使用。
綁定源可以是:
控件自身(通過RelativeSource Self)。
邏輯樹中的父控件(通過RelativeSource AncestorType)。
數據上下文(DataContext)。
元素名稱(ElementName)。
靜態資源(StaticResource)等。


🧪 六、小結

  • 如果你開發的是 UserControl,可以繼續使用普通屬性 + INotifyPropertyChanged

  • 如果你開發的是 自定義控件(繼承 Control 等),請使用依賴屬性。

  • 模板中綁定自身屬性時:

    • TemplateBinding 性能好,適合簡單場景;
    • Binding + RelativeSource 更靈活,適合復雜場景。

📌 推薦結構

控件文件夾結構建議如下:

/Controls└── ImageMessageControl.cs
/Themes└── Generic.xaml

Generic.xaml 示例:

<Style TargetType="{x:Type local:ImageMessageControl}"><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type local:ImageMessageControl}"><Border BorderBrush="Gray" BorderThickness="1" Padding="4"><TextBlock Text="{TemplateBinding ImageMessage}" /></Border></ControlTemplate></Setter.Value></Setter>
</Style>

小結

其實依賴屬性最大的用處還是,可以給前臺暴露屬性。方便我們通過XAML設置屬性。這篇文章主要介紹如何在自定義模板的時候,如何使用依賴屬性,避免踩坑。

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

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

相關文章

DOM型XSS破壞

目錄 首先 然后 第一種 第二種&#xff08;DOM&#xff09; HTMLCollection HTML Relationships Custom 解 首先 <script>//urlencode解碼 //location接口的hash屬性是一個字符串&#xff0c;包含一個“#”后跟位置URL的片段標識符。如果URL沒有片段標識符&#…

Linux C 多線程基本操作

我們已經了解進程的基本概念&#xff1a;進程是正在執行的程序&#xff0c;并且是系統資源分配的基本單位。當用戶需要在一臺計算機上去完成多個獨立的工作任務時&#xff0c;可以使用多進程的方式&#xff0c;為每個獨立的工作任務分配一個進程。多進程的管理則由操作系統負責…

C語言基礎:二維數組練習題

1. 一個二維數組賦了初值&#xff0c;用戶輸入一個數&#xff0c;在該二維數組中查找。找到則返回行列位置&#xff0c;沒找到則提示。#include <stdio.h>int main() {int arr[3][3] {{1, 2, 3},{4, 5, 6},{7, 8, 9}};int t;printf("要查找的數&#xff1a;")…

Java面試題034:一文深入了解MySQL(6)

Java面試題029&#xff1a;一文深入了解MySQL&#xff08;1&#xff09; Java面試題030&#xff1a;一文深入了解MySQL&#xff08;2&#xff09; Java面試題031&#xff1a;一文深入了解MySQL&#xff08;3&#xff09; Java面試題032&#xff1a;一文深入了解MySQL&#x…

Java基礎教程(011):面向對象中的構造方法

10-面向對象-構造方法 構造方法也叫做構造器、構造函數。 作用&#xff1a;在創建對象的時候給成員變量進行初始化的。 ? 一、構造方法的特點特點說明與類同名構造方法的名稱必須與類名相同沒有返回類型構造方法沒有返回值&#xff0c;甚至不能寫 void自動調用使用 new 創建對…

Adobe Photoshop:數字圖像處理的終極工具指南

Hi&#xff0c;我是布蘭妮甜 &#xff01;Adobe Photoshop自1990年問世以來&#xff0c;已經成為數字圖像處理領域的標桿和代名詞。這款強大的軟件不僅徹底改變了攝影、設計和藝術創作的方式&#xff0c;還深刻影響了我們消費和感知視覺內容的文化方式。從專業攝影師到社交媒體…

本期來講講什么是LVS集群?

集群和分布式 集群&#xff08;Cluster&#xff09;&#xff0c;解決某個問題將多臺計算機組合形成的系統群。 常見的集群類型&#xff1a; 負載均衡(LoadBalancing&#xff0c;簡稱LB)&#xff1a;由多個相同配置的主機組成&#xff0c;每個主機經過調度承擔部分訪問&#…

JVM 類加載過程筆記

一、概述 JVM&#xff08;Java Virtual Machine&#xff09;在運行 Java 程序時&#xff0c;需要將 .class 字節碼文件加載到內存中&#xff0c;并轉換成可以被 JVM 執行的數據結構&#xff0c;這一過程就是 類加載過程&#xff08;Class Loading Process&#xff09;。 JVM 的…

基于爬蟲技術的電影數據可視化系統 Python+Django+Vue.js

本文項目編號 25002 &#xff0c;文末自助獲取源碼 \color{red}{25002&#xff0c;文末自助獲取源碼} 25002&#xff0c;文末自助獲取源碼 目錄 一、系統介紹二、系統錄屏三、啟動教程四、功能截圖五、文案資料5.1 選題背景5.2 國內外研究現狀 六、核心代碼6.1 查詢數據6.2 新…

如何用 LUKS 和 cryptsetup 為 Linux 配置加密

在信息安全愈發重要的今天&#xff0c;為 Linux 系統盤配置全盤加密已經成為很多企業和個人的選擇。LUKS&#xff08;Linux Unified Key Setup&#xff09;配合工具 cryptsetup 可以在不犧牲性能的前提下實現高強度加密。本文將通過一個故事化的場景&#xff0c;介紹整個配置過…

VIVADO技巧_BUFGMUX時序優化

1.版本說明日期作者版本說明2025xxxx風釋雪初始版本 2.概述 基于VIVADO時序約束&#xff0c;BUFGMUX多路時鐘選擇原語的設計3.原語介紹 7系列FPGA/UltraSCale/UltraSCaleBUFGMUX_CTRL BUFGMUX_CTRL_inst (.O(O), // 1-bit output: Clock output.I0(I0), // 1-bit input: Cloc…

服務器系統時間不準確怎么辦?

服務器系統時間不準確可能會導致日志錯亂、任務調度失敗、SSL證書校驗錯誤等問題。以下是解決辦法&#xff1a;&#x1f310; 一、同步系統時間的方法1. 使用 timedatectl 命令&#xff08;適用于 systemd 系統&#xff09;timedatectl set-ntp true # 開啟自動同步 timedatect…

零信任產品聯合寧盾泛終端網絡準入,打造隨需而變、精準貼合業務的網絡安全訪問體系

零信任網絡訪問控制&#xff08;Zero Trust Network Access&#xff0c;ZTNA&#xff0c;文中零信任皆指 ZTNA&#xff09;基于“永不信任&#xff0c;持續驗證”的理念&#xff0c;打破了企業基于傳統網絡邊界進行防護的固有模式。在當前日趨復雜的網絡環境下&#xff0c;內部…

【未限制消息消費導致數據庫CPU告警問題排查及解決方案】

一、背景 某天下午&#xff0c;上游系統同一時間突然下了三個大合同數據&#xff0c;平均每個合同數據實例在6萬以上的量級&#xff0c;短短幾分鐘內瞬間有20萬左右的流量涌入系統。 而在正常情況下&#xff0c;系統1天處理的流量也不過2千量級&#xff0c;當時數據庫指標監控告…

iOS開發 Swift 速記2:三種集合類型 Array Set Dictionary

初級代碼游戲的專欄介紹與文章目錄-CSDN博客 我的github&#xff1a;codetoys&#xff0c;所有代碼都將會位于ctfc庫中。已經放入庫中我會指出在庫中的位置。 這些代碼大部分以Linux為目標但部分代碼是純C的&#xff0c;可以在任何平臺上使用。 源碼指引&#xff1a;github源…

Apache基礎配置

一、Apache安裝# 安裝apache [rootwebserver ~]# yum install httpd -y# 在防火墻中放行web服務 [rootwebserver ~]# firewall-cmd --permanent --add-servicehttp success [rootwebserver ~]# firewall-cmd --permanent --add-servicehttps success# 開啟服務 [rootwebserver …

Python100個庫分享第37個—BeautifulSoup(爬蟲篇)

目錄專欄導讀&#x1f4da; 庫簡介&#x1f3af; 主要特點&#x1f6e0;? 安裝方法&#x1f680; 快速入門基本使用流程解析器選擇&#x1f50d; 核心功能詳解1. 基本查找方法find() 和 find_all()CSS選擇器2. 屬性操作3. 文本提取&#x1f577;? 實戰爬蟲案例案例1&#xff…

石子入水波紋效果:頂點擾動著色器實現

水面波紋的真實模擬是計算機圖形學中一個經典且重要的課題,廣泛應用于游戲、影視和虛擬現實等領域。本文將從技術原理和實現細節出發,系統介紹如何利用**頂點擾動(Vertex Displacement)**技術,結合多種輔助方法,打造既真實又高效的水面波紋效果。 一、頂點擾動的核心思想…

【FFmpeg 快速入門】本地播放器 項目

目錄 &#x1f308;前言&#x1f308; &#x1f4c1; 整體架構 詳細流程 &#x1f4c1; 數據流向? &#x1f4c1; 隊列設計?編輯 &#x1f4c1; 線程設計 &#x1f4c1; 音視頻同步 &#x1f4c1; 音頻輸出設計 &#x1f4c1; 視頻輸出設計 &#x1f4c1; 總結 …