TemplateBinding與Binding區別,以及WPF自定義控件開發的遭遇

在上一次的文章WPF OnApplyTemplate 不執行 或者執行滯后的疑惑談到怎么正確的開發自定義控件,我們控件的樣式中,屬性的綁定一般都是用TemplateBinding來完成,如下一個基本的按鈕樣式:

<Style x:Key="SimpleButton" TargetType="{x:Type Button}" BasedOn="{x:Null}"><Setter Property="FocusVisualStyle" Value="{DynamicResource SimpleButtonFocusVisual}"/><Setter Property="Background" Value="{DynamicResource NormalBrush}"/><Setter Property="BorderBrush" Value="{DynamicResource NormalBorderBrush}"/><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type Button}"><!-- We use Grid as a root because it is easy to add more elements to customize the button --><Grid x:Name="Grid"><Border x:Name="Border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}"/><!-- Content Presenter is where the text content etc is placed by the control --><!-- The bindings are useful so that the control can be parameterized without editing the template --><ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" RecognizesAccessKey="True"/></Grid><!--Each state sets a brush on the Border in the template --><ControlTemplate.Triggers><Trigger Property="IsKeyboardFocused" Value="true"><Setter Property="BorderBrush" Value="{DynamicResource DefaultedBorderBrush}" TargetName="Border"/></Trigger><Trigger Property="IsMouseOver" Value="true"><Setter Property="Background" Value="{DynamicResource MouseOverBrush}" TargetName="Border"/></Trigger><Trigger Property="IsPressed" Value="true"><Setter Property="Background" Value="{DynamicResource PressedBrush}" TargetName="Border"/><Setter Property="BorderBrush" Value="{DynamicResource PressedBorderBrush}" TargetName="Border"/></Trigger><Trigger Property="IsEnabled" Value="true"/><Trigger Property="IsEnabled" Value="false"><Setter Property="Background" Value="{DynamicResource DisabledBackgroundBrush}" TargetName="Border"/><Setter Property="BorderBrush" Value="{DynamicResource DisabledBorderBrush}" TargetName="Border"/><Setter Property="Foreground" Value="{DynamicResource DisabledForegroundBrush}"/></Trigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter>
</Style>

我們看到,許多屬性都是用TemplateBinding來完成的,也就是我們在使用控件和開發自定義控件時,都能夠做到數據的展示數據的行為分開,使用數據驅動UI的思想,對于較復雜行為的控件,我們也可以在OnApplyTemplate方法中通過GetTemplateChild方法來獲取到,當然,這個方法的執行時機是必須在布局過程中,如果在這之前就使用了內部的控件,那么必然會報Null錯誤。
所以一般的樣式開發中,都是用TemplateBinding來完成,說說今天的遭遇。我就是開發一個分頁控件,點擊上一頁,下一頁的時候,當前的頁碼要能夠跟著變化。顯示這個頁碼的控件那就是TextBlock,TemplateBinding了PageIndex依賴屬性。控件的后臺代碼中,對上一頁下一頁的事件,就是修改PageIndex的值。運行起來,頁碼不會跟著變化!好,修改成Binding方式,如下:

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

這樣能夠正常工作了。但是WPF自家的控件用的都是TemplateBinding,都沒這問題,不甘心,繼續網上找資料,發現一篇說是自定義的依賴屬性使用TemplateBinding就是有問題的,這種bug微軟怎么能不發現呢,并且這都.Net4.5了,內心感覺一定不是這樣的,終于啊,找到問題所在了,并且是在一篇排版雜亂無章的小博客中找到的。

TemplateBinding作為一種性能優化后的Binding使用,據說是Binding比較耗資源,這個沒有求證過,但是我的程序中那么多Binding,運行起來也不覺得慢啊,或者說是用在模板中的一種Binding優化方式。既然是優化過的,那么它就會少一些東西,其中一個是數據流動的方向。TemplateBinding是單方向的,即數據源到目標的方向。這也解釋了TreeViewItem官方的樣式中,那個三角形的小箭頭,它對于是否展開(IsExpanded屬性)的屬性綁定用的就不是TempalteBinding,因為他不能反過去更新數據源啊。

<Style x:Key="SimpleTreeViewItem" d:IsControlPart="True" TargetType="{x:Type TreeViewItem}"><Setter Property="Background" Value="Transparent"/><Setter Property="HorizontalContentAlignment" Value="{Binding Path=HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/><Setter Property="VerticalContentAlignment" Value="{Binding Path=VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/><Setter Property="Padding" Value="1,0,0,0"/><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type TreeViewItem}"><Grid><Grid.ColumnDefinitions><ColumnDefinition MinWidth="19" Width="Auto"/><ColumnDefinition Width="Auto"/><ColumnDefinition Width="*"/></Grid.ColumnDefinitions><Grid.RowDefinitions><RowDefinition Height="Auto"/><RowDefinition/></Grid.RowDefinitions><!--注意這里--><ToggleButton x:Name="Expander" Style="{DynamicResource SimpleTreeViewItemToggleButton}" IsChecked="{Binding Path=IsExpanded, RelativeSource={RelativeSource TemplatedParent}}" ClickMode="Press"/><Border Grid.Column="1" x:Name="Selection_Border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}"><ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" x:Name="PART_Header" ContentSource="Header"/></Border><ItemsPresenter Grid.Column="1" Grid.ColumnSpan="2" Grid.Row="1" x:Name="ItemsHost"/></Grid><ControlTemplate.Triggers><Trigger Property="IsExpanded" Value="false"><Setter Property="Visibility" Value="Collapsed" TargetName="ItemsHost"/></Trigger><Trigger Property="HasItems" Value="false"><Setter Property="Visibility" Value="Hidden" TargetName="Expander"/></Trigger><Trigger Property="IsSelected" Value="true"><Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" TargetName="Selection_Border"/><Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/></Trigger><MultiTrigger><MultiTrigger.Conditions><Condition Property="IsSelected" Value="true"/><Condition Property="IsSelectionActive" Value="false"/></MultiTrigger.Conditions><Setter Property="Background" Value="red" TargetName="Selection_Border"/><Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/></MultiTrigger><Trigger Property="IsEnabled" Value="false"><Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/></Trigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter>
</Style>

但是在分頁控件的這個頁碼屬性上,是不需要反方向更新數據源這個功能的。所以問題也不是這兒,但必須注意這一點,開發自定義控件的時候非常重要。

另外一個區別就是Converter,WPF中的Binding都是能夠通過Converter來轉換數據的,所以不管是TemplateBinding還是Binding都是夠使用Converter來設置轉換器,區別在于沒有設置轉換器的情況下,例如將int類型的數據綁定到TextBox的Text屬性上,Binding會將值轉換成字符串來顯示,然而TemplateBinding就不會,這就是頁碼不能顯示,也不會變化的原因。我立馬弄了一個字符串類型頁碼依賴屬性,TemplateBinding到這個Text屬性上,可以工作了。但不會這么傻,再寫一個轉換器給TemplateBinding,這也是能夠工作的。所以當數據源的類型和目標的類型不一致時,TemplateBinding需要自己寫轉換器來完成

總結一下TemplateBinding與Binding區別

(1)TemplateBinding只是單方向的數據綁定
(2)TemplateBinding不會自動轉換數據類型

轉載于:https://www.cnblogs.com/HelloMyWorld/p/6744894.html

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

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

相關文章

Layui版本的WPF開源控件庫-Layui-WPF

大家好&#xff0c;我是沙漠盡頭的狼。今天介紹一款Layui風格的WPF開源控件庫&#xff0c;倉庫信息如下&#xff1a;倉庫地址&#xff1a;https://github.com/Layui-WPF-Team/Layui-WPF倉庫截圖&#xff1a;Layui-WPF關于Layui請點擊此鏈接[1]了解&#xff0c;本文不做介紹&…

Mycat 之 通過Keepalived 實現高可用

一、系統拓撲圖 一、操作方法 參考本博客的Nginx Keepalived 實現高可用轉載于:https://blog.51cto.com/12965094/2164485

Nginx使用upstream實現動靜分離

一、為什么要進行動靜分離 分離資源&#xff0c;減少不必要到的請求消耗&#xff0c;減少請求延時。 注&#xff1a;我這里&#xff0c;是nginx處理靜態資源&#xff0c;apache處理動態資源。 場景分析&#xff1a; 1、未分離之前的場景步驟 &#xff08;1&#xff09;客戶…

HMAC

HMAC 的用途 HMAC 算法主要應用于身份驗證&#xff0c;用法如下&#xff1a; 1.客戶端發出登錄請求2.服務器返回一個隨機值&#xff0c;在會話記錄中保存這個隨機值3.客戶端將該隨機值作為密鑰&#xff0c;用戶密碼進行 hmac 運算&#xff0c;遞交給服務器4.服務器讀取數據庫中…

JS的原型鏈和繼承

原型和原型鏈 原型prototype&#xff0c;在創建新函數的時候&#xff0c;會自動生成&#xff0c;而prototype中也會有一個constructor&#xff0c;回指創建該prototype的函數對象。 __proto__是對象或者實例中內置的[[prototype]]&#xff0c;其指向的是產生該對象的對象的prot…

Android 的滑動分析以及各種實現

一、滑動效果的產生滑動一個View&#xff0c;本質區別就是移動一個View。改變當前View所在的坐標&#xff0c;原理和動畫相似不斷改變坐標位置實現。實現View的滑動就必須監聽滑動的事件&#xff0c;并且根據事件傳入的坐標&#xff0c;動態且不斷改變View的坐標&#xff0c;從…

微軟產品 .NET 6 遷移之旅

“.NET性能不行&#xff01;”“.NET有什么像樣的產品嗎&#xff01;&#xff1f;”“升級到.NET 6有什么好處&#xff01;&#xff1f;”……聽人扯淡還不如看看微軟自己是怎么做的。本文將匯總一下微軟的開發博客——這些博客均涉及微軟將產品和服務遷移到.NET 6的成果。博客…

Navicat 連接 RDS數據庫

場景介紹&#xff1a; 隨著業務量的逐漸增加&#xff0c;公司的數據庫壓力也會逐漸增大&#xff0c;使用自己購買的esc創建的mysql的話&#xff0c;還得考慮相應的dba維護&#xff0c;也比較繁瑣&#xff0c;說不定還做的并不完美&#xff0c;這時&#xff0c;RDS就派上用場了&…

bzoj1045 糖果傳遞

Description 有n個小朋友坐成一圈&#xff0c;每人有ai個糖果。每人只能給左右兩人傳遞糖果。每人每次傳遞一個糖果代價為1。 Input 第一行一個正整數nn<1000000&#xff0c;表示小朋友的個數&#xff0e;接下來n行&#xff0c;每行一個整數ai&#xff0c;表示第i個小朋友得…

BEGINNING SHAREPOINT#174; 2013 DEVELOPMENT 第9章節--client對象模型和REST APIs概覽 client對象模型API范圍...

BEGINNING SHAREPOINT 2013 DEVELOPMENT 第9章節--client對象模型和REST APIs概覽 client對象模型API范圍 本章之前提到過。client對象模型應用中一個不足就是缺乏對SP APIs和訪問功能的支持不足。轉載于:https://www.cnblogs.com/yutingliuyl/p/6748382.html

為.NET應用添加截圖功能

本文介紹了 .NET 實現截圖功能的思路和過程&#xff0c;如果你僅想了解最后的解決方案&#xff0c;可以直接查看文章末尾。截圖的功能我們應該都經常使用&#xff0c;在開發軟件時&#xff0c;我們有時也或多或少需要提供這方面的功能&#xff0c;無論是為用戶更方便提供遠程診…

K8S集群Master高可用實踐

本文將在前文基礎上介紹k8s集群的高可用實踐&#xff0c;一般來講&#xff0c;k8s集群高可用主要包含以下幾個內容&#xff1a;1、etcd集群高可用2、集群dns服務高可用3、kube-apiserver、kube-controller-manager、kube-scheduler等master組件的高可用 其中etcd實現的辦法較為…

[轉載]智能科普:VR、AR、MR的區別

智能科普&#xff1a;VR、AR、MR的區別 http://news.zol.com.cn/553/5534833.html news.zol.com.cn 2015-11-23 16:00近日&#xff0c; 獲得谷歌5億美元融資的技術公司Magic Leap在WSJD展會中放出了一段實錄視頻&#xff0c;引起不小騷動。如今&#xff0c;也有媒體稱他們為MR公…

PHP項目中,記錄錯誤日志

一、場景介紹&#xff1a; 環境&#xff1a;LNMP 我們通常是通過nginx的錯誤日志來分析分錯的&#xff0c;也就是我們在各個server中定義的error_log。 比如下面這樣&#xff0c;就是將錯誤日志定義在/etc/nginx/logs/error/www.xiaobudiu.top.log&#xff0c;發生錯誤&#xf…

持續集成指南:GitLab 的 CI/CD 工具配置與使用

1前言寫代碼這項工作&#xff0c;本質就是將工作自動化&#xff0c;減少手工操作提供效率&#xff0c;因為人的本質都是懶狗&#xff0c;程序員也不能例外&#xff0c;為了各種意義的效率提升&#xff08;懶&#xff09;&#xff0c;我們需要持續集成工具&#xff0c;將代碼測試…

php 錯誤日志 redis' already loaded in Unknown on line 0

環境介紹&#xff1a;LNMP 報錯信息&#xff1a;注&#xff1a;這個php_errors.log 是我在php.ini 中定義的錯誤日志路徑 問題原因&#xff1a; 報錯信息給出的意思是&#xff1a;redis和memcache 模塊已經加載過問題解決&#xff1a; php加載模塊有兩種方式&#xff0c;一種是…

第一周作業

我的Git賬號&#xff1a;AI1452349541 和代碼圖 這是我在電腦和手機上下的網易有道詞典 &#xff0c; C也下了。 ***學習內容總結*** 感覺任務并不是很難&#xff0c;有些任務沒完成是 因為還沒買電腦不好弄&#xff0c;下周電腦一定到位。 ***遇到的問題…

升級MariaDB為10.1版本

2019獨角獸企業重金招聘Python工程師標準>>> CentOS中升級mariadb為10.1GA版本。 1、如果有&#xff0c;停止服務 systemctl stop mariadb 2、卸載原來的數據庫服務 yum -y remove mari* 3、刪除數據庫文件 rm -rf /var/lib/mysql/* 4.創建/etc/yum.repos.d/MariaDB…

第一篇文章

第一次寫博客。歡迎各位大牛捧場轉載于:https://www.cnblogs.com/clnchanpin/p/6753665.html

羊了個羊的Ignite大會又來啦

據說最近羊了個羊非常火啊&#xff5e;可惜沒有時間精力研究。不過&#xff0c;薅微軟羊毛的機會我是一定不會錯過的&#xff0c;這不&#xff0c;薅羊毛的機會來了&#xff0c;哈哈哈。作為經常薅微軟羊毛的老司機&#xff0c;今天收到了微軟的郵件&#xff0c;告知有新的羊毛…