当前位置: 首页 > news >正文

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的属性,实现了更高效率的保存机制&#xf…...

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介绍&#xff1a;PCM&#xff08;Puls Code Modulation&#xff09;全称脉码调制录音&#xff0c;PCM录音就是将声音的模拟信号表示成0,1标识的数字信号&#xff0c;未经任何编码和压缩处理&#xff0c;所以可以认为PCM是未经压缩的音频原始格式。PCM格式文件中不包含头部信…...

嵌入式C/C++、FreeRTOS、STM32F407VGT6和TCP:智能家居安防系统的全流程介绍(代码示例)

1. 项目概述 随着物联网技术的快速发展,智能家居安防系统越来越受到人们的重视。本文介绍了一种基于STM32单片机的嵌入式安防中控系统的设计与实现方案。该系统集成了多种传感器,实现了实时监控、报警和远程控制等功能,为用户提供了一个安全、可靠的家居安防解决方案。 1.1 系…...

【Django】django自带后台管理系统样式错乱,uwsgi启动css格式消失的问题

正常情况&#xff1a; ERROR&#xff1a;&#xff08;css、js文件加载失败&#xff09; 问题&#xff1a;CSS加载的样式没有了&#xff0c;原因&#xff1a;使用了django自带的admin&#xff0c;在使用 python manage.py runserver启动 的时候&#xff0c;可以加载到admin的文…...

解决npm install(‘proxy‘ config is set properly. See: ‘npm help config‘)失败问题

摘要 重装电脑系统后&#xff0c;使用npm install初始化项目依赖失败了&#xff0c;错误提示&#xff1a;‘proxy’ config is set properly…&#xff0c;具体的错误提示如下图所示&#xff1a; 解决方案 经过报错信息查询解决办法&#xff0c;最终找到了两个比较好的方案&a…...

汽车及零部件研发项目管理系统:一汽东机工选择奥博思 PowerProject 提升研发项目管理效率

在汽车行业中&#xff0c;汽车零部件的研发和生产是一个关键的环节。随着汽车市场的不断扩大和消费者需求的不断增加&#xff0c;汽车零部件项目管理的重要性日益凸显。通过有效的项目管理方法及利用先进的数字项目管理系统&#xff0c;可以大幅提高项目的成功率和顺利度&#…...

Vellium:基于Electron与RAG的本地AI创作工作台架构解析

1. 项目概述&#xff1a;Vellium&#xff0c;一个全能的本地AI创作与对话工作台如果你和我一样&#xff0c;既沉迷于与AI进行深度角色扮演对话&#xff0c;又需要它协助进行严肃的写作、整理知识库&#xff0c;并且对数据隐私和本地化运行有执念&#xff0c;那么你一定会对Vell…...

泰拉瑞亚地图编辑器TEdit:5步打造专业级游戏世界的终极指南

泰拉瑞亚地图编辑器TEdit&#xff1a;5步打造专业级游戏世界的终极指南 【免费下载链接】Terraria-Map-Editor TEdit - Terraria Map Editor - TEdit is a stand alone, open source map editor for Terraria. It lets you edit maps just like (almost) paint! It also lets y…...

GlosSI完全攻略:一键实现Steam控制器全局支持的终极方案

GlosSI完全攻略&#xff1a;一键实现Steam控制器全局支持的终极方案 【免费下载链接】GlosSI Tool for using Steam-Input controller rebinding at a system level alongside a global overlay 项目地址: https://gitcode.com/gh_mirrors/gl/GlosSI 有没有想过&#xf…...

千问 LeetCode 2281.巫师的总力量和 public int totalStrength(int[] strength)

LeetCode 2281. 巫师的总力量和 是一道经典的 贡献法 + 单调栈 + 前缀和的前缀和 题目。题目要求对数组的所有非空连续子数组,计算: min(subarray) * sum(subarray) 的总和,并对 10^9 + 7 取模。 ✅ 解题思路(核心思想) 我们 不枚举所有子数组(那样是 O(n)),而是 枚…...

基于Web Audio与Three.js的VR音乐可视化系统开发实践

1. 项目概述&#xff1a;当音乐可视化遇上VR&#xff0c;一次沉浸式体验的探索最近在折腾一个挺有意思的项目&#xff0c;叫“VersaYT/JellyVR”。乍一看这个名字&#xff0c;可能有点摸不着头脑&#xff0c;它其实是一个将YouTube音乐视频的音频频谱&#xff0c;实时转化为虚拟…...

ETS2LA:为《欧洲卡车模拟2》带来终极智能驾驶体验的5大核心功能

ETS2LA&#xff1a;为《欧洲卡车模拟2》带来终极智能驾驶体验的5大核心功能 【免费下载链接】Euro-Truck-Simulator-2-Lane-Assist Plugin based interface program for ETS2/ATS. 项目地址: https://gitcode.com/gh_mirrors/eur/Euro-Truck-Simulator-2-Lane-Assist 想…...

京城汤泉夜宿体验:寻找最舒适的放松之地

引言在快节奏的城市生活中&#xff0c;越来越多的人开始追求一种能够彻底放松身心的方式。洗浴汤泉作为其中的一种选择&#xff0c;以其独特的魅力吸引了众多都市人。本文将带您走进京城的洗浴汤泉世界&#xff0c;特别介绍合韵汤泉&#xff0c;帮助您找到最适合自己的放松之地…...

C++数据结构进阶|排序:吃透O(n log n)核心算法,搞定面试高频考点

文章目录 前言 一、希尔排序&#xff08;Shell Sort&#xff09;—— 插入排序的进阶优化版 二、快速排序&#xff08;Quick Sort&#xff09;—— C面试手写高频&#xff0c;实际开发首选 三、归并排序&#xff08;Merge Sort&#xff09;—— 稳定排序的核心选择 四、堆排…...

期末课程论文不用卷!虎贲等考 AI:真文献 + 规范稿,轻松高效拿高分

一到期末、结课、学分冲刺阶段&#xff0c;课程论文就成了大学生最集中的压力点。选题不会定、框架搭不起来、文献找不到、内容写得太空、格式一塌糊涂、查重还容易超标…… 随便一项都能让原本简单的作业变得耗时又费力。 很多同学用通用 AI 凑字数&#xff0c;结果文献假、逻…...

前端八股文面经大全:上海威派格前端实习(2026-05-07)·面经深度解析

前言 大家好&#xff0c;我是木斯佳。 相信很多人都感受到了&#xff0c;在AI浪潮的席卷之下&#xff0c;前端领域的门槛在变高&#xff0c;纯粹的“增删改查”岗位正在肉眼可见地减少。曾经热闹非凡的面经分享&#xff0c;如今也沉寂了许多。但我们都知道&#xff0c;市场的…...