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 服务中,以及它们如何支持验证和强制。

课后作业

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/46885.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android GWP-Asan使用与实现原理

目录 一、 背景 二、GWP-Asan介绍 2.1 什么是GWP-ASan 2.2 GWP-Asan与其他几类工具对比 2.3 GWP-ASan与其它内存分配器的兼容性 三、GWP-Asan如何使用 3.1 app进程 3.2 native进程 四、GWP-Asan实现原理 4.1 进程启用GWP-Asan 4.2 初始化 4.3 内存分配 4.3.1 内存…

【AI资讯】7.19日凌晨OpenAI发布迷你AI模型GPT-4o mini

性价比最高的小模型 北京时间7月19日凌晨,美国OpenAI公司推出一款新的 AI 模型“GPT-4o mini”,即GPT-4o的更小参数量、简化版本。OpenAI表示,GPT-4o mini是目前功能最强大、性价比最高的小参数模型,性能逼近原版GPT-4&#xff0…

CH01_WPF概述

第1章:WPF概述 本章目标 了解Windows图形演化了解WPF高级API了解分辨率无关性概念了解WPF体系结构了解WPF 4.5 WPF概述 ​ 欢迎使用 Windows Presentation Foundation (WPF) 桌面指南,这是一个与分辨率无关的 UI 框架,使用基于矢量的呈现引…

Linux云计算 |【第一阶段】ENGINEER-DAY4

主要内容: 配置Linux网络参数、配置静态主机名、查看/修改/激活/禁用网络连接、指定DNS、虚拟网络连接、虚拟机克隆、SSH客户端、SCP远程复制、SSH无密码验证(SERVICE-DAY5)、虚拟网络类型 一、网络参数配置 修改网卡配置文件主要是需要配置…

农田自动化闸门的结构组成与功能解析

在现代化的农业节水灌溉领域中,农田自动化闸门的应用越来越广泛。它集成了先进的技术,通过自动化控制实现水资源的精准调度和高效利用。本文将围绕农田自动化闸门的结构组成,详细介绍其各个部件的功能和特点。 农田自动化闸门主要由闸门控制箱…

STM32智能农业灌溉系统教程

目录 引言环境准备智能农业灌溉系统基础代码实现:实现智能农业灌溉系统 4.1 数据采集模块 4.2 数据处理与决策模块 4.3 通信与网络系统实现 4.4 用户界面与数据可视化应用场景:农业灌溉管理与优化问题解决方案与优化收尾与总结 1. 引言 智能农业灌溉系…

隐语隐私计算实训营「联邦学习」第 3 课:隐语架构概览

【隐私计算实训营】是蚂蚁集团隐语开源社区出品的线上课程,自实训营上线以来,获得行业内外广泛关注,吸引上千余名开发者报名参与。本次暑期夏令营课程中,除了最新上线的「联邦学习系列」,还包含了「隐私保护数据分析」…

喜报!极限科技再获国家发明专利:《一种超大规模分布式集群架构的数据处理方法》,引领大数据处理技术创新

近日,极限数据(北京)科技有限公司(简称:极限科技)传来喜讯,公司再次斩获国家发明专利授权。这项名为"一种超大规模分布式集群架构的数据处理方法"的专利(专利号&#xff1…

数学基础【俗说矩阵】:初等矩阵和矩阵的初等行变化关系推导

初等矩阵和矩阵的初等行变换 初等矩阵 矩阵的初等行变换 对单位阵E进行一次初等行变化得到的阵叫做初等阵。 这里只能进行一次初等行变换。 置换阵 给矩阵【左乘】一个【置换阵】,相当与对该矩阵进行了一次【置换阵】对应的【置换】初等行变换; 数…

​人人开源renren-security:基于SpringBoot、Vue3、ElementPlus等框架开发的权限管理系统

摘要: 随着信息技术的快速发展,企业的信息系统安全需求日益凸显。renren-security是一套基于SpringBoot、MyBatis-Plus、Shiro、Vue3、ElementPlus等框架开发的权限管理系统,它旨在为企业提供高效、安全、易用的权限管理解决方案。本文详细阐…

Serverless技术的市场调研与发展分析

目录 一、 Serverless基础 1.1 Serverless产生的背景 1.2 什么是Serverless 1.3 Serverless架构优势 1.3.1 按需使用的资源管理 1.3.2 简化业务运维复杂度 1.4 Serverless和Service Mesh相同点 1.5 Serverless基础架构 1.5.1 函数管理 1.5.2 事件触发器 1.5.3 函数的…

【论文阅读笔记】Hierarchical Neural Coding for Controllable CAD Model Generation

摘要 作者提出了一种CAD的创新生成模型,该模型将CAD模型的高级设计概念表示为从全局部件排列到局部曲线几何的三层神经代码的层级树,并且通过指定目标设计的代码树来控制CAD模型的生成或完成。具体而言,一种带有“掩码跳过连接”的向量量化变…

html网页使用tesseract实现OCR文字识别

即在前端实现OCR文字识别 1.前端代码 <!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>OCR文字识别…

[SUCTF 2018]GetShell

查看源代码发现源码 if($contentsfile_get_contents($_FILES["file"]["tmp_name"])){ 保存上传文件在临时文件目录$datasubstr($contents,5); 切片从第五个字符开始之后的所有字符foreach ($black_char as $b) { 看看有没有黑名单有…

XMind PRO 最新2024版 思维导图软件安装下载教程,免费领取,图文步骤详解(内置软件包,可激活使用)

文章目录 软件介绍软件下载安装步骤激活步骤 软件介绍 XMind 2024是一款功能强大的思维导图和头脑风暴软件&#xff0c;它帮助用户清晰地组织和表达思维&#xff0c;融合艺术与创造力&#xff0c;使思维过程更加高效和直观。以下是关于XMind 2024的详细介绍&#xff1a; 主要功…

[数据集][目标检测]婴儿车检测数据集VOC+YOLO格式1073张5类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;1073 标注数量(xml文件个数)&#xff1a;1073 标注数量(txt文件个数)&#xff1a;1073 标注…

Java 和 SpringBoot 中的设计模式 详解

一、建造者模式 发生场景 假如有一结果api结果返回值的类Person&#xff0c;其在代码中频繁被使用。如果要使用它&#xff0c;一般的方法是&#xff1a; public class Main {public static void main(String[] args) {//方法1&#xff0c;使用全量的构造函数Person person1 …

MF173:将多个工作表转换成PDF文件

我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#xff0c;可以大大提高自己的工作效率&#xff0c;而且可以提高数据的准确度。“VBA语言専攻”提供的教程一共九套&#xff0c;分为初级、中级、高级三大部分&#xff0c;教程是对VBA的系统讲解&#…

三、初识C语言(3)

1.操作符 &#xff08;1&#xff09;算术操作符 - * / % 商 余&#xff08;取模&#xff09; 小算法&#xff1a; 若a<b&#xff0c;则a%b a 若a%b c&#xff0c;则0 < c < b-1 若两个int 类型数相除&#xff0c;结果有小数会被舍弃。 保留小数…

LeetCode岛屿的最大面积(深度搜索)/什么是深搜,简单案例回顾图用邻接表实现图的深度优先遍历。

看这道题不懂深度搜索的可以看看下面讲述 岛屿的最大面积 解题思路 代码 class Solution {int dfs(vector<vector<int>>& grid, int cur_i, int cur_j) {//确定边界if((cur_i >0 && cur_i < grid.size()) && (cur_j >0 &&…