WPF——Control与Template理解
文章目录
- 一、前言
- 二、控件
- 三、模板
- 3.1 DataTemplate
- 3.2 ControlTemplate
- 3.3 ContentPresenter
- 四、结语
一、前言
最近又翻看了下刘铁猛的《深入浅出WPF》,发现对模板章节中的部分内容有了更深的体会,所以写篇文扯扯。
文章标题是Control与Template,翻译成控件与模板。
将两者放一起不是无缘无故的,在WPF中,两者关系相当密切。
二、控件
如果有人问你什么是控件,你会怎么回答?
像界面上的按钮、文本框、滚动条啊,都是控件。
所以控件可以理解为界面的组成元素。
以上是我之前的回答,这样的回答没啥问题,很直观,很多人听了都能明白,虽然可能不太严谨。
不过如果继续问,
那为什么叫控件,而不是其它名称。这种界面上的可交互的图案,称作图形元素,不是更直观、更贴切?
我可能会回答,控件这个名称是根据Control这个单词翻译过来的,所以叫控件。
对面可能继续问,那为什么英文叫Control,而不是Graphic Element。
此时我陷入了沉思,确实,为什么会用Control这个单词来命名呢。
如何消除这个疑惑,最简单的就是百度,
百度词条
控件是指对数据和方法的封装。
控件可以有自己的属性和方法,其中属性是控件数据的简单访问者,方法则是控件的一些简单而可见的功能、控件创建过程包含设计、开发、调试工作,然后是控件的使用。
先别管百度说的是对是错,但显然并不直观。你跟非程序员这么解释,他可能还是不懂。
那么从专业的角度来看,这段对控件的描述有没有道理呢。
学过程序的都知道,程序的本质是数据结构与算法。
界面上的控件呈现了一定内容,并且提供了一些交互方式,用户通过交互可以改变程序状态。
那么,控件呈现的内容本质是什么?
是数据。
控件提供的交互方式本质/目的是什么?
我想应该是程序逻辑,比如你按下按钮,最终程序内部会执行一个方法(一段代码,即程序逻辑),程序状态可能会因此发生一些改变。
所以,控件既是数据的表现形式,以让用户可以直观地看到数据;又是算法的表现形式,以让用户方便地操作逻辑。
作为“表现形式”,每个控件都是为了实现某种用户操作算法和直观显示某种数据而生的,一个控件看上去是什么样子由它的“算法内容”和“数据内容”决定,这也是哲学中常说的内容决定形式。
这样看来,百度的这段话还是挺有道理的,更接近控件的本质。
三、模板
接下来回到WPF中的模板。
在以往的GUI技术中,控件内部的逻辑和数据是固定的,程序员不能改变(比如WinForms/Qt(QWidget));对于控件的外观,程序员能做的改变也非常有限,一般就是设置控件的属性,想改变控件的内部结构更是不可能。如果想扩展一个控件的功能或更改其外观让其更适合业务逻辑,哪怕只有一丁点改变,也经常要创建控件的子类或创建用户控件(UserControl)。造成这个局面的根本原因就是数据和算法的“形式”与“内容”耦合的太紧了 。
在WPF中,通过引入模板(Template),将数据和算法的“内容”和“形式”解耦了。
WPF中的Template分为两大类:
- ControlTemplate,是算法内容的表现形式,一个控件怎样组织其内部结构才能让它更符合业务逻辑、让用户操作起来更舒服就是由它来控制的。它决定了控件“长成什么样子”,并让程序员有机会在控件原有的内部逻辑基础上扩展自己的逻辑。
- DataTemplate,是数据内容的表现形式,一条数据显示成什么样子,是简单文本还是直观的图形动画就由它来决定。
一言蔽之,Template就是“外衣”——ControlTemplate是控件的外衣,DataTemplate是数据的外衣。
WPF中的控件不再具有固定的形象,仅仅是算法内容和数据内容的载体。
你可以把控件理解为一组操作逻辑穿上了一套衣服,换套衣服就能变成另外一个模样。你看到的控件默认形象实际上就是出厂时微软为它穿上的默认服装。
3.1 DataTemplate
在实际项目中,DataTemplate相较于ControlTemplate,往往是用的比较多一些。
正如其名,它是数据的模板/外观。使用时,往往会在外层绑上一个对象,然后在内部将对象的属性绑定到各种控件。
只要将绑定的控件更换,显示的外观也会发生变化。即一样的内容可以用不同形式来展现,软件设计称之为“数据-视图”(Data-View)模式。
在WPF开发中,DataTemplate常用的地方有三处,分别是:
- ContentControl的ContentTemplate属性,相当于给ContentControl的内容穿衣服。
- ItemsControl的ItemTemplate属性,相当于给ItemsControl的数据项穿衣服。
- GridViewColumn的CellTemplate属性,相当于给GridViewColumn单元格里的数据穿衣服。
3.2 ControlTemplate
前面说过,
你看到的控件默认形象实际上就是出厂时微软为它穿上的默认服装。
因为ControlTemplate有默认服装,且大部分时候默认服装已经够用了,所以很少有人会手动去修改它。
实际项目中,即使要给ControlTemplate做替换,也往往是用成熟的UI工具包,引入项目中,应用其样式即可。
这很合理,前面也说了,每个控件都是为了实现某种用户操作算法和直观显示某种数据而生的。而这些特定的操作算法是由控件的本质决定的,显然这部分内容较数据来讲是更为固定,交由微软或者专业的组件开发商决定没有问题。
不过,这也并不意味着普通程序员就完全不需要去了解ControlTemplate。因为某些时候,确实也会需要修改它们。
《WPF深入浅出》一书中说到,
实际项目中,ControlTemplate主要由两大用处:
- 通过更换ControlTemplate改变控件外观,使之具有更优的用户体验及外观。
- 接触ControlTemplate,程序员与设计师可以并行工作,程序员可以先用WPF标准控件进行编程,等设计师工作完成后,只需把新的ControlTemplate应用到程序中就可以了。
不过考虑到国内WPF开发的现状,应该很少有设计师和程序员工作完全分离的。所以ControlTemplate的使用上也集中在第一点了。
但第一点,听起来似乎和之前所说的冲突了,ControlTemplate不是呈现算法的吗,怎么变成改变控件外观的了。
其实这并不矛盾,因为控件的外观和控件的本质息息相关。
- Button为什么形状都差不多,一般就是一个椭圆或矩形,可点击,点击后会凹下去。
- TextBox为什么都是一个矩形框,里面可输入文字。
- ScrollBar为什么都是一个长条,你可以拖动它移动。
还记得算法是什么吗?
每本编程入门书都会说,算法是解决问题的办法。
这些控件之所以有这样的外观和交互方式,并不是凭空产生的,而是人设计出来的。显然这样的设计就是为了解决一类问题,即它是一种算法。
当你对控件效果不满意时,就可能需要更改其外观,以贴合实际需求。
此时,我对ControlTemplate又有了一层理解。控件模板描述的是控件外观以及外观对外界刺激所做出的反应(比如各种事件/按钮鼠标触摸后的背景色变化等),而外观和对刺激的反应更深层的含义是该类控件要解决的问题的解决方案。
下面是一个实际开发中的ControlTemplate应用场景,我需要在鼠标移动到按钮上时,按钮的背景色发生变红色(这是为了使鼠标移动到按钮的操作有反馈感):
<Style TargetType="Button"><Style.Triggers><Trigger Property="IsMouseOver" Value="True"><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="Button"><Border Background="red"><ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center"/></Border></ControlTemplate></Setter.Value></Setter></Trigger></Style.Triggers>
</Style>
如代码所示,用触发器检验鼠标是否在控件上,若是则修改其控件模板,主要就是将控件模板外的border的背景色变红。
3.3 ContentPresenter
实际上Button的结构就是这么简单,
<Border><ContentPresenter/>
</Border>
一个边框加一个ContentPresenter就组成了一个按钮。
那么,ContentPresenter是什么?
我们可以通过反编译看到其中结构,下面是我整理出来的一个类关系图:
你会发现ContentPresenter的结构和ContentControl高度重合。
这边我也不卖关子,也不想花太多篇幅去深究它们的关系。
你可以把ContentPresenter直接理解成控件的数据内容模板DataTemplate。
有的控件继承了ContentControl,我称之为内容控件。
也有部分控件没有继承它,比如TextBox,
也因此,TextBox的默认控件模板中不存在ContentPresenter。这也很好理解,都没有数据内容,何来数据内容呈现?
你可能会问,那它的Text属性不是数据内容?
当然是,但从控件的角度来看,Text这样的属性已经是相当基础了,就是一段字串(有点类似于“原子数据”),而内容控件的Content可能是有分割必要的,比如Button中可能会有文字描述/图标等。因此我个人倾向于,Text本身这种简单的特性导致了它不作为内容模板出现。
四、结语
写了这么多,主要就是谈了谈对控件以及两个模板的理解。
这种理解更像是WPF开发(也不限于WPF)的内功,不对写代码直接产生效率提升,但会有长远的积极影响。
相关文章:
WPF——Control与Template理解
文章目录 一、前言二、控件三、模板3.1 DataTemplate3.2 ControlTemplate3.3 ContentPresenter 四、结语 一、前言 最近又翻看了下刘铁猛的《深入浅出WPF》,发现对模板章节中的部分内容有了更深的体会,所以写篇文扯扯。 文章标题是Control与Template&a…...
华为HCIA学习(一)
文章目录 一.根据考试题总结知识点(一题一点)二.上午学习三.下午学习四.今天只做了70题,需要的可以找我 一.根据考试题总结知识点(一题一点) 二.上午学习 ① VRP系统是VRP是华为公司从低端到高端的全系列路由器、交换…...
使用jmeter+ant+jenkins+git搭建自动化测试平台
最近正在学习自动化测试,于是随手搭建了一下jmeterantjenkinsgit平台。 接下来,我会按照jdk,jmeter,ant,jenkins,git这个顺序一步一步的搭建起来。 一、jdk。这个就不多说了。我用的是1.8版本的,配环境变…...
C# Winform中在DataGridView中添加Button按钮,操作Button按钮
.Net的DataGridView控件中,提供了一种列的类型,叫 DataGridViewButtonColumn ,这种列类型是展示为一个 按钮,可以给button赋予相应的text,并且,此button可以用来做处理事件的判断依据。 DataGridViewButto…...
Docker 网络学习
docker的网络模式 当你开始大规模使用Docker时,你会发现需要了解很多关于网络的知识。Docker作为目前最火的轻量级容器技术,有很多令人称道的功能,如Docker的镜像管理。然而,Docker同样有着很多不完善的地方,网络方面…...
django创建web服务器
安装 pip install django 创建项目 django-admin startproject report django-admin startapp data //project下可创建多个app 执行使用 python manage.py migrate //orm代码到数据库 python manage.py runserver 0.0.0.0:80 权限管理 python manage.py createsuperuser 创建…...
极光笔记 | 推送服务数据中心选择:合规性与传输效率的双重考量
随着全球化进程的深入,跨境数据传输与存储问题已经变得愈发重要。推送服务的数据中心节点选择不仅关乎数据访问速度和用户体验,同时也直接牵扯到数据合规性和安全保障。EngageLab Push深知这一点,为了满足更多国际客户和全球用户触达需求&…...
Python灰帽编程——初识Python上
1. Python 简介 常用安全工具语言示例perljoomscan whatwebrubymetasploit-frameworkpythonsqlmap pocsuite3gogoby 1.1 Python 起源 1.1.1 语言的作者 贵铎范罗萨姆(Guido van Rossum)荷兰人于1989 年圣诞节始创了python。 大神就是大神࿰…...
OLED透明屏交互技术:开创未来科技的新篇章
OLED透明屏交互技术作为一项前沿的科技创新,正在以其高透明度、触摸和手势交互等特点,引领着未来科技的发展。 不仅在智能手机、可穿戴设备和汽车行业有着广泛应用,还在广告和展示领域展现出巨大的潜力。 那么,尼伽在这篇文章中将…...
揭秘Spring Boot内嵌Tomcat原理
tomcat 介绍 tomcat 是 web容器(servlet 容器),不管请求是访问静态资源HTML、JSP还是java接口,对tomcat而言,都是通过servlet访问: 访问静态资源,tomcat 会交由一个叫做DefaultServlet的类来处…...
分类散点图 stripplot() 加辅助线axhline() 多图合一
分类散点图 stripplot 加辅助线axhline 多图合一 效果图代码 画图没有什么可说的,直接上图 效果图 代码 # 绘制图, 查看是否数值在阈值上 plt.figure(figsize(30, 18)) n 0 for header, value_list in info_dict.items():ref_value_list ref_info_dic…...
一文告诉你为什么时序场景下 TDengine 数据订阅比 Kafka 好
在 TDengine 3.0 中,我们对流式计算、数据订阅功能都进行了再升级,帮助用户极大简化了数据架构的复杂程度,降低整体运维成本。TDengine 提供的类似消息队列产品的数据订阅、消费接口,本质上是为了帮助应用实时获取写入 TDengine 的…...
reg与wire的用法,证明reg可以在右边,wire型在左边,来作组合逻辑处理。
reg与wire的用法,证明reg可以在右边,wire型在左边,来作组合逻辑处理。 1,RTL2,生成的原理图 1,RTL 参考文献: 1,verilog 中 wire 和reg 的使用 2,解决一个assign问题&…...
Studio One6.2简体中文免费最新版本宿主软件
对于一些有创作需求的朋友来说,为自己写的歌制作伴奏是很平常的。今天要和大家分享的就是自己写的歌怎么做伴奏,自己做伴奏的软件有哪些。Studio One是宿主软件界的一个后起之秀,推出的时间不久,但是受到了大量音乐制作人的推崇。…...
算法刷题 week2
目录 week21. 二维数组中的查找题目题解(单调性扫描) O(nm) 2.替换空格题目题解(线性扫描) O(n)(双指针扫描) O(n) 3.从尾到头打印链表题目题解(遍历链表) O(n) week2 1. 二维数组中的查找 题目 题解 (单调性扫描) O(nm) 核心在于发现每个子矩阵右上角的数的性质࿱…...
子网的划分
强化计算机网络发现王道没有这一块的内容,导致做题稀里糊涂。于是个人调研补充。 子网划分是将一个大型IP网络划分成更小的子网,以实现更有效的网络管理和资源分配。 原因: 提高网络性能:子网划分可以减少广播域的大小ÿ…...
Docker安装与卸载
Docker安装与卸载 安装 yum install -y yum-utils \device-mapper-persistent-data \lvm2 --skip-broken更新本地镜像源 打开终端或 SSH 连接到 Rocky Linux 的服务器。 进入 /etc/yum.repos.d/ 目录,该目录包含 Rocky Linux 的 yum 配置文件。 cd /etc/yum.repo…...
【Davinci开发】:开发过程问题记录及总结
开发过程问题总结 1、SWC访问系统OS Timer返回值异常a、代码发现,RTE接口为未连接状态b、连接后,仍然有问题,单步调试,发现没有访问权限当新平台基于之前平台的代码而延续开发时(应用代码相同,但是芯片已经更换),记录开发过程中遇所到的问题,单步调试,逐一排查。 1、…...
数据结构——排序算法——冒泡排序
冒泡排序1 void swap(vector<int> arr, int i, int j) {int temp arr[i];arr[i] arr[j];arr[j] temp;}void bubbleSort1(vector<int> arr) {for (int i 0; i < arr.size() - 1; i){for (int j 0; j < arr.size() - 1 - i; j){if (arr[j] > arr[j 1…...
vscode使用
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、pandas是什么?二、使用步骤 1.引入库2.读入数据总结 前言 提示:这里可以添加本文要记录的大概内容: 例如:…...
python经典百题之求前!的和
题目:求12!3!…20!的和 方法一: 使用for循环和阶乘函数计算每项的值,再将每项的值累加起来。 def factorial(n):if n 0:return 1else:return n * factorial(n-1)sum 0 for i in range(1, 21):sum factorial(i) * iprint(sum)优点&#…...
C语言入门Day_22 初识指针
目录 前言: 1.内存地址 2.指针的定义 3.指针的使用 4.易错点 5.思维导图 前言: 之前我们学过变量可以用来存储数据,就像一个盒子里面可以放不同的球一样。 这是一个方便大家理解专业概念的比喻。 在计算机世界里面,数据实…...
【面试必刷TOP101】删除链表的倒数第n个节点 两个链表的第一个公共结点
目录 题目:删除链表的倒数第n个节点_牛客题霸_牛客网 (nowcoder.com) 题目的接口: 解题思路: 代码: 过啦!!! 题目:两个链表的第一个公共结点_牛客题霸_牛客网 (nowcoder.com) …...
手刻 Deep Learning -第壹章 -PyTorch教学-激励函数与感知机入门(上)
一、前言 本文接续前篇教学 Pytorch 与线性回归 ,本文着重在 Activation Function ( 中文称 激励函数 ),我们会介绍激励函数 (也有人称 激活函数? 激发函数? ) 为什么会有用…...
物理内存分配
目录 内核物理内存分配接口 内存分配行为(物理上) 内存分配的行为操作 内存 三个水位线 水线计算 水位线影响内存分配行为 内存分配核心__alloc_pages 释放页 1、内核物理内存分配接口 struct page *alloc_pages(gfp_t gfp, unsigned int ord…...
RFID产线自动化升级改造管理方案
应用背景 在现代制造业中,产线管理是实现高效生产和优质产品的关键环节,产线管理涉及到生产过程的监控、物料管理、工艺控制、质量追溯等多个方面,有效的产线管理可以提高生产效率、降低成本、改善产品质量,并满足市场需求的变化…...
全量数据采集:不同网站的方法与挑战
简介 在当今数字化时代中,有数据就能方便我们做出很多决策。数据的获取与分析已经成为学术研究、商业分析、战略决策以及个人好奇心的关键驱动力。本文将分享不同网站的全量数据采集方法,以及在这一过程中可能会遇到的挑战。 部分全量采集方法 1. 撞店…...
Redis——渐进式遍历和数据库管理命令
介绍 如果使用keys * 这样的操作,将Redis中所有的key都获取到,由于Redis是单线程工作,这个操作本身又要消耗很多时间,那么就会导致Redis服务器阻塞,后续的操作无法正常执行 而渐进式遍历,通过多次执行遍历…...
如何打造可视化警务巡防通信解决方案
近年来,科学技术飞速发展,给予了犯罪分子可乘之机。当面临专业化的犯罪分子、高科技的犯罪手段,传统警务模式似乎不能满足警方打击犯罪的需要,因此当今公安工作迫切需要构建智能化、系统化、信息化的警务通信管理模式。 警务人员…...
ATF(TF-A) SPMC威胁模型-安全检测与评估
安全之安全(security)博客目录导读 ATF(TF-A) 威胁模型汇总 目录 一、简介 二、评估目标 1、数据流图 三、威胁分析 1、信任边界 2、资产 3、威胁代理 4、威胁类型 5、威胁评估 5.1 端点在直接请求/响应调用中模拟发送方或接收方FF-A ID 5.2 篡改端点和SPMC之间的…...
wordpress301改不回来/不受限制的浏览器
本专栏总结王利涛《C语言嵌入式Linux高级编程》第二期课程 文章目录一、程序的编译、链接1)编译过程2)链接过程二、链接脚本1)不同的代码段如何组装?2)链接脚本示例3)不同开发环境下的链接脚本4)…...
做摘抄的网站/seo建站技术
推荐一波我写的任务管理软件(持续扩展完善) 主要功能可以每天规划任务,并查看今天还剩下多少秒,以及总完成率. CSDN下载:https://download.csdn.net/download/qq_41806966/12545118 需要源码可以去我的Github:https://github.com/1711680493/Application 里面的ShendiTaskM…...
英语网站大全免费/市场调研报告怎么写的
使用JavaScript开发IE浏览器本地插件实例 投稿:junjie 字体:[增加 减小] 类型:转载 时间:2015-02-18 我要评论 这篇文章主要介绍了使用JavaScript开发IE浏览器本地插件实例,本文讲解使用JS注册表的方式开发一个IE浏览器本地插件,需…...
用于制作网页的工具软件/专业关键词优化平台
问题简介 我写爬虫,用到了asyncio相关的事件循环,新建了一个线程去run_forever(),在docker中运行。后来程序有异常,主线程挂了,但是竟然不报错。查了很久,才找出来。 如果你新建一个线程去运行一般的死循环…...
delphi xe10网站开发/搜索数据
直接上代码… /*** author gxq* date * <p>* 自定义注解(实现数据库查询,接口访问权限一系列)*/ Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE}) //表示此作用作用的目标&…...
南平 网站建设/推广公司是做什么的
环境: 2020款MacBook Pro13.3 八核M1/8G/256G 问题描述: 公司Macbook Pro,换了好几位员工使用,他们走了,不知道谁的账户启用了激活锁,重置系统后开机要激活,忘了激活锁账户密码如何向苹果申请…...