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.mzph.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;告知有新的羊毛…