CH04_依赖项属性
第4章:依赖项属性
本章目标
- 理解依赖项属性
- 理解属性验证
依赖项属性
属性与事件是.NET抽象模型的核心部分。WPF使用了更高级的依赖项属性(Dependency Property)功能来替换原来.NET的属性,实现了更高效率的保存机制,还添加了附加功能,如属性变更通知以及强制回调、属性值继承(在逻辑树中向下传播默认属性值的能力)以及属性有效性验证等。同时,依赖项属性也是WPF许多重要功能的基础,包括动画、数据绑定以及样式。
使用依赖项属性包括三个部分,定义依赖项属性;注册依赖项属性以及添加属性包装器。
定义依赖项属性
定义依赖项属性,使用三个修饰词,public、static、readonly。数据类型为DependecyProperty,而每一个依赖项属性都会有一个去掉“Property”的CLR属性和他对应,而我们在xaml中访问的都是CLR属性。
根据约定,定义依赖项属性的字段的名称是在普通属性的末尾处加上单词"Property"。根据这种命名方式,可以从实际属性的名称中区分出依赖项属性的定义。字段的定义使用了 readoly 关键字,这意味着只能在 FrameworkElement 类的静态构造函数中队旗进行设置。
例如,FrameworkElement 类定义了 Margin 属性,在 FrameworkElement 类中需要使用类似下面的代码来定义Margin 属性:
注册依赖项属性
定义 DependencyProperty对象只是第一步而已。为了使用依赖项属性,还需要使用 WPF注册创建的依赖项属性。这一步骤需要在任何使用属性的代码之前完成,因此必须在与其关联的类的静态构造函数中进行。
WPF 确保 DependencyProperty 对象不能被直接实例化,因为 DependencyProperty 类没有公有的构造函数。相反,只能使用静态的 DependencyProperty Register0方法创建 DependencyProperty实例。WPF 还确保在创建 DependencyProperty 对象后不能改变该对象,因为所有DependencyProperty 成员都是只读的。它们的值必须作为 Register0方法的参数来提供。
下面的代码显示了如何创建 DependencyProperty 对象。在此,FrameworkElement类使用静态构造函数来初始化 MarginProperty:
添加属性包装器
创建依赖项属性的最后一个步骤是使用传统的.NET 属性封装WPF依赖项属性。但典型的过程是检索或设置某个私有字段的值,而WPF属性的属性过程是使用在 DependencyObject 基类中定义的 GetValue()和 SetValue()方法。
共享的依赖项属性
尽管一些类具有不同的继承层次,但他们会共享同一依赖项属性。例如,TextBlock.FontFamily属性和 Control.FontFamily 属性指向同一个静态的依赖项属性,该属性实际上实在 TextElement 类中定义的 TextElement.FontFamilyProperty 依赖项属性。TextElement 类的静态构造函数注册该属性,而 TextBlock 类和Control 类的静态构造函数知识通过调用 DependencyProperty.AddOwner()方法重用该属性:
TextBlock类:
Control类:
附加的依赖项属性
附加属性是一种依赖项属性,由WPF 属性系统管理。不同之处在于附加属性被应用到的类并非定义附加属性的那个类。例如,Grid 类定义了Row 和 Column 附加属性,这两个属性被用于设置Grid 面板包含的元素,以指明这些元素应被放到哪个单元格之中。类似的,DockPancel 类定义了 Dock 附加属性,而 Canvas 类定义了Left、Right、Top和Bottom 附加属性。
为了定义附加属性,需要使用 RegisterAttached() 方法,而不是使用 Register() 方法.下面列举了一个注册Grid.Row 属性的例子:
当创建附加属性时,不必定义.NET 属性封装器。这是因为附加属性可以被用于任何依赖对象。例如,Grid.Row 属性可能被用于 Grid 对象(如果在Grid 控件中嵌套了另一个Grid 控件),也可能被用于其他元素。实际上,Grid.Row 属性甚至可以被用于并不位于 Grid控件中的元素------- 甚至在元素树中根本就不存在 Grid 对象。
不是使用 .NET 属性封装器,反而附加属性需要调佣两个静态方法来设置和获取属性值,这两个方法使用为人熟知的 SetValue() 和 GetValue() 方法(继承自 DependencyObject 类)。这两个静态方法应当命名为 SetPropertyName() 和 GetPropertyName().下面是实现 Grid.Row 附加属性的静态方法:
下面的示例使用代码将元素放到Grid 控件中第一行:
Grid.SetRow(txtElement,0)
也可直接调用 SetValue() 或 GetValue() 方法,从而绕过这两个静态方法:
txtElement.SetValue(Grid.RowProperty,0)
属性验证
在定义任何类型的属性时,都需要面对错误设置属性的可能性。对于传统的.NET属性,可尝试在属性设置器中捕获这类问题。但对于依赖项属性而言,这种方法不合适,因为可能通过WPF 属性系统使用 SetValueO方法直接设置属性。
作为代替,WPF 提供了两种方法来阻止非法值:
- ValidateValueCallback:该回调函数可接受或拒绝新值。通常,该回调函数用于捕获违反属性约束的明显错误。可作为 DependencyProperty.Register()方法的一个参数提供该回调函数。
- CoerceValueCallback:该回调函数可将新值修改为更能被接受的值。该回调函数通常用于处理为相同对象设置的依赖项属性值相互冲突的问题。这些值本身可能是合法的,但当同时应用时它们是不相容的。为了使用这个回调函数,当创建 Framework-PropertyMetadata 对象时(然后该对象将被传递到 DependencyProperty.Register()方法),作为构造函数的一个参数提供该回调函数。
下面是当应用程序试图设置依赖项属性时,所有这些内容的作用过程:
(1) 首先,CoerceValueCallback 方法有机会修改提供的值(通常,使提供的值和其他属性相容),或者返回 DependencyProperty.UnsetValue,这会完全拒绝修改。
(2) 接下来激活 Validate ValueCallback 方法。该方法返回 true 以接受一个值作为合法值,或者返回 false拒纯值。与 Coerce ValueCallback 方法不同,Validate ValueCallback 方法不能访问设置属性的实际对象,这意味着您不能检查其他属性值。
(3) 最后,如果前两个阶段都获得成功,就会触发 PropertyChangedCallback 方法。此时,如果希望为其他类提供通知,可以引发更改事件。
验证回调
DependencyProperty.Register() 方法接受可选的验证回调函数:
MarginProperty = DependencyProperty.Register(
"Margin",
typeof(Thickness),
_typeofThis,
new FrameworkPropertyMetadata(default(Thickness),FrameworkPropertyMetadataOptions.AffectsMeasure), IsMarginValid);
private static bool IsMarginValid(object value)
{return ((Thickness)value).IsValid(allowNegative: true, allowNaN: false, allowPositiveInfinity: true, allowNegativeInfinity: false);
}
强制回调
通过 FrameworkPropertyMetadata 对象使用 CoerceValueCallback 回调函数。
FrameworkPropertyMetadata metadata = new FrameworkPropertyMetadata();
metadata.CoerceValueCallback = new CoerceValueCallback(CoerceMaximum);DependencyProperty.Register("Maximum",typeof(double),typeof(RangeBase),metadata);
可以通过CoerceValueCallback 回调函数处理相互关联的属性。例如,ScrollBar 控件提供了 Maximum、Minimum 和 Value 属性,这些属性都继承自 RangeBase 类。保持对这些属性进行调整的一种方法是使用属性强制。例如,当设置Maximum 属性时,必须使用强制以确保不能小于 Minimum 属性的值:
当设置 Value 属性时,会发送类似的强制过程。对 Value 属性进行强制,确保不会超出由 Minimum 和Maximum 属性定义的范围,使用下面的代码:
Minimum 属性根本不使用值强制。相反,一旦值发生变化,就触发PropertyChangedCallback,然后通过手动触发 Maximum 和 Value 属性的强制过程,使它们适应 Minimum 属性值的变化:
类似的,一旦设置或强制 Maximum 属性的值,那么也会手动强制 Value 属性以适应 Maximum 属性值的变化:
如果设置的值相互冲突,最终结果是 Minimum 属性具有优先权,其次是 Maximum 属性(并且可能会被 Minimum 属性强制),最后是 Value 属性(并且可能会被 Maximum 和 Minimum 属性强制)。
本章小结
本章深入分析了 WPF 依赖项属性。首先介绍如何定义和注册依赖项属性,接下类介绍了如何将它们插入到其他 WPF 服务中,以及它们如何支持验证和强制。
课后作业
无
相关文章:
CH04_依赖项属性
第4章:依赖项属性 本章目标 理解依赖项属性理解属性验证 依赖项属性 属性与事件是.NET抽象模型的核心部分。WPF使用了更高级的依赖项属性(Dependency Property)功能来替换原来.NET的属性,实现了更高效率的保存机制…...
CentOS 7开启SSH连接
1. 安装openssh-server 1.1 检查是否安装openssh-server服务 yum list installed | grep openssh-server如果有显示内容,则已安装跳过安装步骤,否则进行第2步 1.2 安装openssh-server yum install openssh-server2. 开启SSH 22监听端口 2.1 打开ssh…...
代理伺服器分類詳解
代理伺服器的主要分類 代理伺服器可以根據不同的標準進行分類。以下是幾種常見的分類方式: 按協議分類按匿名性分類按使用場景分類 1. 按協議分類 根據支持的協議類型,代理伺服器可以分為以下幾類: HTTP代理:專門用於處理HTT…...
计数,桶与基数排序
目录 一. 计数排序 概念 步骤思路如下 实现代码如下 时间复杂度与空间复杂度 1. 时间复杂度 2. 空间复杂度 计数排序的特点 二. 桶排序 概念 步骤思路如下 实现代码如下 时间复杂度与空间复杂度 1. 时间复杂度 2. 空间复杂度 桶排序的特点 三. 基数排序 概念 步…...
unity渲染人物模型透明度问题
问题1:有独立的手和衣服的模型,但最终只渲染出来半透明衣服 问题2:透明度贴图是正确的但显示却不正确 这上面两个模型的问题都是因为人物模型是一个完整的,为啥有些地方可以正常显示,有些地方透明度却有问题。 其中…...
CH03_布局
第3章:布局 本章目标 理解布局的原则理解布局的过程理解布局的容器掌握各类布局容器的运用 理解 WPF 中的布局 WPF 布局原则 WPF 窗口只能包含单个元素。为在WPF 窗口中放置多个元素并创建更贴近实用的用户男面,需要在窗口上放置一个容器&#x…...
【Oracle】Oracle中的merge into
目录 解释使用场景语法示例案例一案例二 MERGE INTO的优缺点优点:缺点: 注意事项附:Oracle中的MERGE INTO实现的效果,如果改为用MySQL应该怎么实现注意 解释 在Oracle数据库中,MERGE INTO是一种用于对表进行合并&…...
【论文阅读笔记】In Search of an Understandable Consensus Algorithm (Extended Version)
1 介绍 分布式一致性共识算法指的是在分布式系统中,使得所有节点对同一份数据的认知能够达成共识的算法。且算法允许所有节点像一个整体一样工作,即使其中一些节点出现故障也能够继续工作。之前的大部分一致性算法实现都是基于Paxos,但Paxos…...
CentOS 7 网络配置
如想了解请查看 虚拟机安装CentOS7 第一步:查看虚拟机网络编辑器、查看NAT设置 (子网ID,网关IP) 第二步:配置VMnet8 IP与DNS 注意事项:子网掩码与默认网关与 第一步 保持一致 第三步:网络配置…...
2024 React 和 Vue 的生态工具
react Vue...
AI学习指南机器学习篇-t-SNE模型应用与Python实践
AI学习指南机器学习篇-t-SNE模型应用与Python实践 在机器学习领域,数据的可视化是非常重要的,因为它可以帮助我们更好地理解数据的结构和特征。而t-SNE(t-distributed Stochastic Neighbor Embedding)是一种非常强大的降维和可视…...
小试牛刀-Telebot区块链游戏机器人
目录 1.编写目的 2.实现功能 2.1 Wallet功能 2.2 游戏功能 2.3 提出功能 2.4 辅助功能 3.功能实现详解 3.1 wallet功能 3.2 游戏功能 3.3 提出功能 3.4 辅助功能 4.测试视频 Welcome to Code Blocks blog 本篇文章主要介绍了 [Telebot区块链游戏机器人] ❤博主…...
使用github actions构建多平台electron应用
1. 创建electron项目 使用pnpm创建项目 pnpm create quick-start/electron 2. 修改electron-builder.yml文件 修改mac的target mac:target:- target: dmgarch: universal 3. 添加workflow 创建 .github/workflows/main.yml 文件 name: Build/release Electron appon:work…...
java通过pdf-box插件完成对pdf文件中图片/文字的替换
需要引入的Maven依赖: <!-- pdf替换图片 --><dependency><groupId>e-iceblue</groupId><artifactId>spire.pdf.free</artifactId><version>5.1.0</version></dependency> java代码: public AjaxResult replacepd…...
鸿蒙 next 5.0 版本页面跳转传参 接受参数 ,,接受的时候 要先定义接受参数的类型, 代码可以直接CV使用 [教程]
1, 先看效果 2, 先准备好两个页面 index 页面 传递参数 import router from ohos.routerEntry Component struct Index {Statelist: string[] [星期一, 星期二,星期三, 星期四,星期五]StateactiveIndex: number 0build() {Row() {Column({ space: 10 }) {ForEach(this.list,…...
【electron6】浏览器实时播放PCM数据
pcm介绍:PCM(Puls Code Modulation)全称脉码调制录音,PCM录音就是将声音的模拟信号表示成0,1标识的数字信号,未经任何编码和压缩处理,所以可以认为PCM是未经压缩的音频原始格式。PCM格式文件中不包含头部信…...
嵌入式C/C++、FreeRTOS、STM32F407VGT6和TCP:智能家居安防系统的全流程介绍(代码示例)
1. 项目概述 随着物联网技术的快速发展,智能家居安防系统越来越受到人们的重视。本文介绍了一种基于STM32单片机的嵌入式安防中控系统的设计与实现方案。该系统集成了多种传感器,实现了实时监控、报警和远程控制等功能,为用户提供了一个安全、可靠的家居安防解决方案。 1.1 系…...
【Django】django自带后台管理系统样式错乱,uwsgi启动css格式消失的问题
正常情况: ERROR:(css、js文件加载失败) 问题:CSS加载的样式没有了,原因:使用了django自带的admin,在使用 python manage.py runserver启动 的时候,可以加载到admin的文…...
解决npm install(‘proxy‘ config is set properly. See: ‘npm help config‘)失败问题
摘要 重装电脑系统后,使用npm install初始化项目依赖失败了,错误提示:‘proxy’ config is set properly…,具体的错误提示如下图所示: 解决方案 经过报错信息查询解决办法,最终找到了两个比较好的方案&a…...
汽车及零部件研发项目管理系统:一汽东机工选择奥博思 PowerProject 提升研发项目管理效率
在汽车行业中,汽车零部件的研发和生产是一个关键的环节。随着汽车市场的不断扩大和消费者需求的不断增加,汽车零部件项目管理的重要性日益凸显。通过有效的项目管理方法及利用先进的数字项目管理系统,可以大幅提高项目的成功率和顺利度&#…...
Keil开发IDE
Keil开发IDE 简述Keil C51Keil ARMMDK DFP安装 简述 Keil公司是一家业界领先的微控制器(MCU)软件开发工具的独立供应商。Keil公司由两家私人公司联合运营,分别是德国慕尼黑的Keil Elektronik GmbH和美国德克萨斯的Keil Software Inc。Keil公…...
数据结构与算法05堆|建堆|Top-k问题
一、堆 1、堆的介绍 堆(heap)是一种满足特定的条件的完全二叉树,主要可以分为大根堆和小根堆。 大根堆(max heap):任意节点的值大于等于其子节点的值。小根堆(min heap)࿱…...
【精简版】jQuery 中的 Ajax 详解
目录 一、概念 二、jQuery 发送 GET 请求 三、jQuery 发送 POST 请求 四、$.ajax() 方法 1、含义 2、settings 选项 ① type 属性 ② async 属性 ③ headers 属性 ④ contentType 属性 ⑤ processData 属性 ⑥ data 属性 ⑦ timeout 属性 ⑧ beforeSend(jqXHR) 方…...
win10删除鼠标右键选项
鼠标右键菜单时,发现里面的选项特别多,找一下属性,半天找不到。删除一些不常用的选项,让右键菜单变得干净整洁。 1、按下键盘上的“winR”组合按键,调出“运行”对话框,输入“regedit”命令,点击…...
分层评估的艺术:sklearn中的策略与实践
分层评估的艺术:sklearn中的策略与实践 在机器学习中,评估模型性能是一个至关重要的步骤。然而,对于不平衡的数据集,传统的评估方法可能会产生误导性的结果。分层评估(Stratified Evaluation)是一种确保评…...
排序系列 之 快速排序
!!!排序仅针对于数组哦本次排序是按照升序来的哦代码后边有图解哦 介绍 快速排序英文名为Quick Sort 基本思路 快速排序采用的是分治思想,即在一个无序的序列中选取一个任意的基准元素base,利用base将待排序的序列分…...
【银河麒麟服务器操作系统】java进程oom现象分析及处理建议
了解银河麒麟操作系统更多全新产品,请点击访问麒麟软件产品专区:https://product.kylinos.cn 现象描述 某服务器系统升级内核至4.19.90-25.22.v2101版本后仍会触发oom导致java进程被kill。 现象分析 oom现象分析 系统messages日志分析,故…...
Redis的AOF持久化策略(AOF的工作流程、AOF的重写流程,操作演示、注意事项等)
文章目录 缓冲AOF 策略(append only file)AOF 的工作流程AOF 缓冲区策略AOF 的重写机制重写完的AOF文件为什么可以变小?AOF 重写流程 缓冲AOF 策略(append only file) AOF 的核心思路是 “实时备份“,只要我添加了新的数据或者更新了新的数据࿰…...
共享模型之无锁
一、问题提出 1.1 需求描述 有如下的需求,需要保证 account.withdraw() 取款方法的线程安全,代码如下: interface Account {// 获取余额Integer getBalance();// 取款void withdraw(Integer amount);/*** 方法内会启动 1000 个线程…...
下载安装VSCode并添加插件作为仓颉编程入门编辑器
VSCode下载地址:下载 Visual Studio Code - Mac、Linux、Windows 插件下载:GitCode - 全球开发者的开源社区,开源代码托管平台 仓颉社区中下载解压 cangjie.vsix 插件 打开VSCode 按 Ctrl Shift X 弹出下图 按照上图步骤依次点击选中我们下…...
wordpress建站毕业论文/信息流广告投放流程
一、 RunLoop初识 日常的开发工作中,我们几乎很少注意RunLoop,因为我们基本上“用不到”RunLoop。包括我在内应该有很多人都不了解这个东西,只是听说过。最近有空查了不少资料终于把RunLoop运行原理搞清楚了。 本文会对RunLoop的原理进行深入…...
苏州制作网站的有几家/网站排名在线优化工具
(图片来源:网络) 2022年2月4日,由量子经济发展联盟(QED-C)和总部位于加利福尼亚州的量子软件和服务公司QC Ware赞助,欧洲量子工业联盟和加拿大量子工业协助的Hyperion Research进行的一项新研究…...
论坛网站开发平台/网络推广方法有哪些
DTOJ3489 可怜与超市(supermarket)题目题目描述输入格式输出格式样例样例输入1样例输出1样例输入2样例输出2数据范围与提示题解题目 题目描述 九条可怜有bbb块钱,她准备去超市买东西 超市有nnn样商品,其中第iii个商品的价格是ci…...
网站怎么做微信扫描登录网站/whois查询 站长工具
一、修改Flex builder 1.用无格式编辑器打开FlashBuilder.ini 2.把zh_CN替换成"en_US" 二、修改MyEclipse插件 1.用无格式编辑器打开MyEclipse8.5\configuration\config.ini 2.最后添加osgi.nlen_US 三、修改Eclipse插件 1.用无格式编辑器打开eclipse.ini 2.顶部加入…...
行业网站建设公司/怎样看网页的友情链接
我们逛街,经常会看到店铺关门或转让,是什么原因搞得我们实体经济前景一片暗淡呢?我们简单分析下: 1、消费模式的改变:随着互联网的快速发展和普及,以及电子商务的发展,人们的生活观念也逐渐受到…...
凡科网做网站花多少钱/互动营销平台
Arch一直在我笔记本里边,只是玩gentoo时我不进Arch了,现在回归Arch,升级到了最新,用上了gentoo的最新的2.6.31内核(自己配置,无initrd),引导程序用的grub4dos:Arch的启动脚本非常优雅,这也是我一眼就喜欢上Archlinux的原因之一:这是我的LXDE桌面:关机时的界面...