WPF 依赖属性和附加属性
除了普通的 CLR 属性, WPF 还有一套自己的属性系统。这个系统中的属性称为依赖属性。
1. 依赖属性
为啥叫依赖属性?不叫阿猫阿狗属性?
通常我们定义一个普通 CLR 属性,其实就是获取和设置一个私有字段的值。假设声明了 100 个 CLR 属性,每个属性占用 8 个字节(byte)的私有字段。那么实例化 10000 个这个类,就至少消耗了 100 * 8 * 10000 = 7.63M 内存。实际上,并非用到所有的属性。这就造成了内存浪费。
如何解决这种属性资源浪费的问题?
现实中一个例子,假设出去旅游,不可能把所有的日常生活用品都带去,一般也就带上日常换洗衣物,像锅碗瓢盆、洗衣粉、厕纸、洗发水等都要带上,岂不乱成一锅。所以,有些东西可以在要用的时候再去获取。
这就是 WPF 依赖属性的理念, 依赖属性本身没有值, 它依赖绑定源来获取值。
在 UserControl 中定义一个依赖属性,snippet 快捷方式(propdp),
public partial class DependencyPropertyDemo : UserControl
{/// <summary>/// 获取或设置MyProperty的值/// </summary> public string MyProperty{get => (string)GetValue(MyPropertyProperty);set => SetValue(MyPropertyProperty, value);}/// <summary>/// 标识 MyProperty 依赖属性。/// </summary>public static readonly DependencyProperty MyPropertyProperty =DependencyProperty.Register(nameof(MyProperty), typeof(string), typeof(DependencyPropertyDemo), new PropertyMetadata(default(string)));public DependencyPropertyDemo(){InitializeComponent();}
}
可以进方法 DependencyProperty.Register
查看,实质是调用内部 RegisterCommon
方法把属性注册到一个 Hashtable
,
private static Hashtable PropertyFromName = new Hashtable();private static DependencyProperty RegisterCommon(string name,Type propertyType,Type ownerType,PropertyMetadata defaultMetadata,ValidateValueCallback validateValueCallback){//...lock (DependencyProperty.Synchronized)DependencyProperty.PropertyFromName[(object) key] = (object) dependencyProperty;//...}
这有点类似设计模式中的 享元模式(Flyweight Pattern)
,使用哈希表存储已经创建的内存对象,来减少内存消耗。
通过 GetValue/SetValue方法, 可以获取/设置依赖属性(绑定数据源)的值。
疑问:我们没有在 DependencyPropertyDemo 类中定义 GetValue/SetValue 方法,为什么也能使用呢?
因为它们已在基类中定义好了。
实际上,任何继承于 DependencyObject
的类中都可以定义依赖属性。我们用到的可视化控件基本都是继承于 Viusal
的,自然可以声明依赖属性。
2. 附加属性
附加属性,其实也是依赖属性。
使用 sinppet (propa)快捷方式创建一个附加属性,
public static readonly DependencyProperty MyAttachedProperty =DependencyProperty.RegisterAttached("MyAttached",typeof(string),typeof(MyAttachedHelper),new FrameworkPropertyMetadata(default(string),flags: FrameworkPropertyMetadataOptions.Inherits));public static string GetMyAttached(DependencyObject target)
{return (string)target.GetValue(MyAttachedProperty);
}public static void SetMyAttached(DependencyObject target, string value)
{target.SetValue(MyAttachedProperty, value);
}
可以看到,它最终也是调用 DependencyProperty.RegisterCommon
来注册属性,GetValue/SetValue 方法一样也是基类 DependencyObject
中的 GetValue/SetValue 方法。
只是附加属性的使用场景不太一样:
依赖属性: 当希望类中某个属性支持数据绑定时, 可以用依赖属性。
附加属性: 当希望类可以绑定到某个数据源,但该类本身又没有这个依赖属性, 就可以借助其它类的依赖属性做绑定。这个过程即:类附加了其它类的一个依赖属性,简称附加属性。
3. 完整示例
在自定义控件中声明一个依赖属性,
public class MyControl : Control
{/// <summary>/// 获取或设置MyProperty的值/// </summary> public string MyProperty{get => (string)GetValue(MyPropertyProperty);set => SetValue(MyPropertyProperty, value);}/// <summary>/// 标识 MyProperty 依赖属性。/// </summary>public static readonly DependencyProperty MyPropertyProperty =DependencyProperty.Register(nameof(MyProperty), typeof(string), typeof(MyControl),new PropertyMetadata(default(string)));static MyControl(){DefaultStyleKeyProperty.OverrideMetadata(typeof(MyControl), new FrameworkPropertyMetadata(typeof(MyControl)));}
}
在另一个类中声明一个附加属性,
public class MyAttachedHelper : DependencyObject
{public static readonly DependencyProperty MyAttachedProperty =DependencyProperty.RegisterAttached("MyAttached",typeof(string),typeof(MyAttachedHelper),new FrameworkPropertyMetadata(default(string),flags: FrameworkPropertyMetadataOptions.Inherits));public static string GetMyAttached(DependencyObject target){return (string)target.GetValue(MyAttachedProperty);}public static void SetMyAttached(DependencyObject target, string value){target.SetValue(MyAttachedProperty, value);}
}
为控件指定样式,
<Style TargetType="{x:Type controls:MyControl}"><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type controls:MyControl}"><Grid Background="DeepPink"><StackPanel Orientation="Horizontal"><TextBlockMargin="4"HorizontalAlignment="Center"VerticalAlignment="Center"Text="{TemplateBinding MyProperty}" /><TextBlockMargin="4"HorizontalAlignment="Center"VerticalAlignment="Center"Text="and" /><TextBlockMargin="4"HorizontalAlignment="Center"VerticalAlignment="Center"Text="{TemplateBinding viewModels:MyAttachedHelper.MyAttached}" /></StackPanel></Grid></ControlTemplate></Setter.Value></Setter>
</Style>
绑定数据源,
public class DpViewModel
{public string Name1 { get; set; }public string Name2 { get; set; }public DpViewModel(){Name1 = "Tom~";Name2 = "Jerry~";}
}
使用控件,
<Grid Width="200" Height="100"><controls:MyControl MyProperty="{Binding Name1}" viewModels:MyAttachedHelper.MyAttached="{Binding Name2}" />
</Grid>
显示结果,
均绑定成功。
相关文章:

WPF 依赖属性和附加属性
除了普通的 CLR 属性, WPF 还有一套自己的属性系统。这个系统中的属性称为依赖属性。 1. 依赖属性 为啥叫依赖属性?不叫阿猫阿狗属性? 通常我们定义一个普通 CLR 属性,其实就是获取和设置一个私有字段的值。假设声明了 100 个 …...
leetcode hot100 删除链表的第n个节点
19. 删除链表的倒数第 N 个结点 已解答 中等 相关标签 相关企业 提示 给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点 # Definition for singly-linked list. # class ListNode(object): # def __init__(self, val0, nextNon…...
MyBatis-Plus分页拦截器,源码的重构(重构total总数的计算逻辑)
1.1创建ThreadLocal工具类(作为业务逻辑结果存放类) package org.springblade.sample.utils;public class QueryContext {private static final ThreadLocal<Long> totalInThreadLocal new ThreadLocal<>();public static void setTotalIn…...
记一MySQL连接速度慢的问题
某一个程序启动速度超级慢,查看日志得知是是在Init DruidDataSource ~ {dataSource-1} inited 这一段耗时最长,这一段是Druid 数据源初始化,进行连接的创建等,使用mysql命令行连接发现连接超级慢,可见是在创建连接的时…...
asp.net core webapi项目中 在生产环境中 进不去swagger
builder.WebHost.UseUrls 是 ASP.NET Core 中配置应用程序监听 URL 或端口的方法。通过使用这个方法,你可以指定应用程序应该在哪些 URL 上运行,以便接收 HTTP 请求。 1.在appsetting.json中 添加 "LaunchUrl": "http://*:327"2.在…...

逆向攻防世界CTF系列63-secret-string-400
逆向攻防世界CTF系列63-secret-string-400 丢入exeinfo,查得zip,解压得四个文件 点进Task,查看源码:Test your luck! Enter valid string and you will know flag 顺理成章地看js 定位check函数 调用了machine的loadcode 跟进…...

Datawhale AI 冬令营学习笔记-零编程基础制作井字棋小游戏
井字棋小游戏是通过豆包MarsCode实现的,没有改动任何的代码,全部是通过对话让AI进行优化和改进。 开始进入正题:进入豆包MarsCode在线IDE,直接点击上方蓝字,或复制链接打开: 豆包 MarsCode - 编程助手。 IDE界面&…...

分布式专题(10)之ShardingSphere分库分表实战指南
一、ShardingSphere产品介绍 Apache ShardingSphere 是一款分布式的数据库生态系统, 可以将任意数据库转换为分布式数据库,并通过数据分片、弹性伸缩、加密等能力对原有数据库进行增强。Apache ShardingSphere 设计哲学为 Database Plus,旨在…...

clickhouse解决suspiciously many的异常
1. 问题背景 clickhouse安装在虚拟机上,持续写入日志时,突然关机,然后重启,会出现clickhouse可以正常启动,但是查询sql语句,提示suspiciously many异常,如图所示 2. 问题修复 touch /data/cl…...
计算机的错误计算(一百九十)
摘要 用两个大模型计算cot(1.234). 其中,1.234是以弧度为单位的角度。结果保留10位有效数字。实验表明,两个的计算公式虽然不同,但是都是正确的。然而,数值计算则是有问题的---包括每一个中间运算与结果。 例1. 计算cot(1.234)…...

STM32-笔记12-实现SysTick模拟多线程流水灯
1、前言 正常STM32实现多线程,需要移植一个操作系统FreeRTOS。但是在这里不移植FreeRTOS怎么实现多线程呢?使用SysTick,那么怎么使用SysTick来模拟多线程呢?前面我们知道SysTick就是一个定时器,它不是在主函数的while循…...

牛客网刷题 ——C语言初阶——BC114 小乐乐排电梯
1.牛客网 :BC114 小乐乐排电梯 题目描述: 小乐乐学校教学楼的电梯前排了很多人,他的前面有n个人在等电梯。电梯每次可以乘坐12人,每次上下需要的时间为4分钟(上需要2分钟,下需要2分钟)。请帮助…...

web三、 window对象,延时器,定时器,时间戳,location对象(地址),本地存储-localStorage,数组去重new Set
一、window对象 window对象 是一个全局对象,也可以说是JavaScript中的 顶级对象 像document、alert()、console.log()这些都是window的属性,基本BOM的属性和方法都是window的 所有通过 var定义 在全局作用域中的 变量 、 函数 都会变成window对象的属…...

【EthIf-13】EthIfGeneral容器配置-01
1.EthIfGeneral类图结构 下面是EthIfGeneral配置参数的类图,比较重要的参数就是配置: 接收中断是否打开发送确认中断是否打开EthIf轮询周期 1.EthIfGeneral参数的含义...

‘pnpm’ 不是内部或外部命令,也不是可运行的程序或批处理文件。
‘pnpm’ 不是内部或外部命令,也不是可运行的程序或批处理文件。 1.情况: npm -v 和 node -v的都正常就是 pnpm-v 无效 检查环境变量也没看出问题 2.分析 没有正确添加环境变量 3.解决 找到npm的全局安装目录 npm list -g --depth 0这里出现了npm的全局安装…...
ECMAScript 6-11 概述
1. ECMA 介绍 ECMA(European Computer Manufacturers Association)是欧洲计算机制造商协会,目标是评估、开发和认可电信和计算机标准。1994年后改名为Ecma国际。 2. ECMAScript 是什么 ECMAScript 是由Ecma国际通过ECMA-262标准化的脚本程…...

sqlalchemy连接dm8 get_columns BIGINT VARCHAR字段不显示
问题 标题即为问题, 问题出现原因 sqlalchemy对应的sqlalchemy_dm源码需要调整 版本说明 python 3.10 dmPython 2.5.5(2.4.8也可以) sqlalchemy1.4.52 sqlalchemy_dm1.4.39 环境说明 部署环境 ubuntu20 开发环境window11 wsl2 ubuntu20 可能会出现的…...

运动控制卡网络通讯的心跳检测之C#上位机编程
本文导读 今天,正运动小助手给大家分享一下如何使用C#上位机编程实现运动控制卡网络通讯的心跳检测功能。 01 ECI2618B硬件介绍 ECI2618B经济型多轴运动控制卡是一款脉冲型、模块化的网络型运动控制卡。控制卡本身最多支持6轴,可扩展至12轴的运动控制…...
QT 控件定义为智能指针引发的bug
问题描述: std::unique_ptr<QStackedLayout> m_stacked_layout; 如上为定义; 调用: Line13ABClient::Line13ABClient(QWidget *parent) : BaseWidget(parent) { // 成员变量初始化 m_get_ready false; m_tittle_wnd…...
Scala项目(图书管理系统)
3、service BookService package org.app package serviceimport org.app.dao.{BookDAO, BorrowRecordDAO} import org.app.models.{BookModel, BorrowRecordModel}import java.time.LocalDateTime import scala.collection.mutable.ListBuffer// 图书业务逻辑层 class BookS…...

JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...

RocketMQ延迟消息机制
两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后…...
React Native 导航系统实战(React Navigation)
导航系统实战(React Navigation) React Navigation 是 React Native 应用中最常用的导航库之一,它提供了多种导航模式,如堆栈导航(Stack Navigator)、标签导航(Tab Navigator)和抽屉…...

《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1
每日一言 生活的美好,总是藏在那些你咬牙坚持的日子里。 硬件:OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写,"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战
在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...

USB Over IP专用硬件的5个特点
USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中,从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备(如专用硬件设备),从而消除了直接物理连接的需要。USB over IP的…...
面试高频问题
文章目录 🚀 消息队列核心技术揭秘:从入门到秒杀面试官1️⃣ Kafka为何能"吞云吐雾"?性能背后的秘密1.1 顺序写入与零拷贝:性能的双引擎1.2 分区并行:数据的"八车道高速公路"1.3 页缓存与批量处理…...

Matlab实现任意伪彩色图像可视化显示
Matlab实现任意伪彩色图像可视化显示 1、灰度原始图像2、RGB彩色原始图像 在科研研究中,如何展示好看的实验结果图像非常重要!!! 1、灰度原始图像 灰度图像每个像素点只有一个数值,代表该点的亮度(或…...

Xcode 16 集成 cocoapods 报错
基于 Xcode 16 新建工程项目,集成 cocoapods 执行 pod init 报错 ### Error RuntimeError - PBXGroup attempted to initialize an object with unknown ISA PBXFileSystemSynchronizedRootGroup from attributes: {"isa">"PBXFileSystemSynchro…...