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

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 属性&#xff0c; WPF 还有一套自己的属性系统。这个系统中的属性称为依赖属性。 1. 依赖属性 为啥叫依赖属性&#xff1f;不叫阿猫阿狗属性&#xff1f; 通常我们定义一个普通 CLR 属性&#xff0c;其实就是获取和设置一个私有字段的值。假设声明了 100 个 …...

leetcode hot100 删除链表的第n个节点

19. 删除链表的倒数第 N 个结点 已解答 中等 相关标签 相关企业 提示 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点 # Definition for singly-linked list. # class ListNode(object): # def __init__(self, val0, nextNon…...

MyBatis-Plus分页拦截器,源码的重构(重构total总数的计算逻辑)

1.1创建ThreadLocal工具类&#xff08;作为业务逻辑结果存放类&#xff09; package org.springblade.sample.utils;public class QueryContext {private static final ThreadLocal<Long> totalInThreadLocal new ThreadLocal<>();public static void setTotalIn…...

记一MySQL连接速度慢的问题

某一个程序启动速度超级慢&#xff0c;查看日志得知是是在Init DruidDataSource ~ {dataSource-1} inited 这一段耗时最长&#xff0c;这一段是Druid 数据源初始化&#xff0c;进行连接的创建等&#xff0c;使用mysql命令行连接发现连接超级慢&#xff0c;可见是在创建连接的时…...

asp.net core webapi项目中 在生产环境中 进不去swagger

builder.WebHost.UseUrls 是 ASP.NET Core 中配置应用程序监听 URL 或端口的方法。通过使用这个方法&#xff0c;你可以指定应用程序应该在哪些 URL 上运行&#xff0c;以便接收 HTTP 请求。 1.在appsetting.json中 添加 "LaunchUrl": "http://*:327"2.在…...

逆向攻防世界CTF系列63-secret-string-400

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

Datawhale AI 冬令营学习笔记-零编程基础制作井字棋小游戏

井字棋小游戏是通过豆包MarsCode实现的&#xff0c;没有改动任何的代码&#xff0c;全部是通过对话让AI进行优化和改进。 开始进入正题&#xff1a;进入豆包MarsCode在线IDE&#xff0c;直接点击上方蓝字&#xff0c;或复制链接打开: 豆包 MarsCode - 编程助手。 IDE界面&…...

分布式专题(10)之ShardingSphere分库分表实战指南

一、ShardingSphere产品介绍 Apache ShardingSphere 是一款分布式的数据库生态系统&#xff0c; 可以将任意数据库转换为分布式数据库&#xff0c;并通过数据分片、弹性伸缩、加密等能力对原有数据库进行增强。Apache ShardingSphere 设计哲学为 Database Plus&#xff0c;旨在…...

clickhouse解决suspiciously many的异常

1. 问题背景 clickhouse安装在虚拟机上&#xff0c;持续写入日志时&#xff0c;突然关机&#xff0c;然后重启&#xff0c;会出现clickhouse可以正常启动&#xff0c;但是查询sql语句&#xff0c;提示suspiciously many异常&#xff0c;如图所示 2. 问题修复 touch /data/cl…...

计算机的错误计算(一百九十)

摘要 用两个大模型计算cot(1.234). 其中&#xff0c;1.234是以弧度为单位的角度。结果保留10位有效数字。实验表明&#xff0c;两个的计算公式虽然不同&#xff0c;但是都是正确的。然而&#xff0c;数值计算则是有问题的---包括每一个中间运算与结果。 例1. 计算cot(1.234)…...

STM32-笔记12-实现SysTick模拟多线程流水灯

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

牛客网刷题 ——C语言初阶——BC114 小乐乐排电梯

1.牛客网 &#xff1a;BC114 小乐乐排电梯 题目描述&#xff1a; 小乐乐学校教学楼的电梯前排了很多人&#xff0c;他的前面有n个人在等电梯。电梯每次可以乘坐12人&#xff0c;每次上下需要的时间为4分钟&#xff08;上需要2分钟&#xff0c;下需要2分钟&#xff09;。请帮助…...

web三、 window对象,延时器,定时器,时间戳,location对象(地址),本地存储-localStorage,数组去重new Set

一、window对象 window对象 是一个全局对象&#xff0c;也可以说是JavaScript中的 顶级对象 像document、alert()、console.log()这些都是window的属性&#xff0c;基本BOM的属性和方法都是window的 所有通过 var定义 在全局作用域中的 变量 、 函数 都会变成window对象的属…...

【EthIf-13】EthIfGeneral容器配置-01

1.EthIfGeneral类图结构 下面是EthIfGeneral配置参数的类图&#xff0c;比较重要的参数就是配置&#xff1a; 接收中断是否打开发送确认中断是否打开EthIf轮询周期 1.EthIfGeneral参数的含义...

‘pnpm’ 不是内部或外部命令,也不是可运行的程序或批处理文件。

‘pnpm’ 不是内部或外部命令&#xff0c;也不是可运行的程序或批处理文件。 1.情况: npm -v 和 node -v的都正常就是 pnpm-v 无效 检查环境变量也没看出问题 2.分析 没有正确添加环境变量 3.解决 找到npm的全局安装目录 npm list -g --depth 0这里出现了npm的全局安装…...

ECMAScript 6-11 概述

1. ECMA 介绍 ECMA&#xff08;European Computer Manufacturers Association&#xff09;是欧洲计算机制造商协会&#xff0c;目标是评估、开发和认可电信和计算机标准。1994年后改名为Ecma国际。 2. ECMAScript 是什么 ECMAScript 是由Ecma国际通过ECMA-262标准化的脚本程…...

sqlalchemy连接dm8 get_columns BIGINT VARCHAR字段不显示

问题 标题即为问题&#xff0c; 问题出现原因 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#上位机编程

本文导读 今天&#xff0c;正运动小助手给大家分享一下如何使用C#上位机编程实现运动控制卡网络通讯的心跳检测功能。 01 ECI2618B硬件介绍 ECI2618B经济型多轴运动控制卡是一款脉冲型、模块化的网络型运动控制卡。控制卡本身最多支持6轴&#xff0c;可扩展至12轴的运动控制…...

QT 控件定义为智能指针引发的bug

问题描述&#xff1a; std::unique_ptr<QStackedLayout> m_stacked_layout; 如上为定义&#xff1b; 调用&#xff1a; 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…...

springboot 百货中心供应链管理系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;百货中心供应链管理系统被用户普遍使用&#xff0c;为方…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法

树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作&#xff0c;无需更改相机配置。但是&#xff0c;一…...

进程地址空间(比特课总结)

一、进程地址空间 1. 环境变量 1 &#xff09;⽤户级环境变量与系统级环境变量 全局属性&#xff1a;环境变量具有全局属性&#xff0c;会被⼦进程继承。例如当bash启动⼦进程时&#xff0c;环 境变量会⾃动传递给⼦进程。 本地变量限制&#xff1a;本地变量只在当前进程(ba…...

java 实现excel文件转pdf | 无水印 | 无限制

文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...

376. Wiggle Subsequence

376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...

如何将联系人从 iPhone 转移到 Android

从 iPhone 换到 Android 手机时&#xff0c;你可能需要保留重要的数据&#xff0c;例如通讯录。好在&#xff0c;将通讯录从 iPhone 转移到 Android 手机非常简单&#xff0c;你可以从本文中学习 6 种可靠的方法&#xff0c;确保随时保持连接&#xff0c;不错过任何信息。 第 1…...

在Ubuntu中设置开机自动运行(sudo)指令的指南

在Ubuntu系统中&#xff0c;有时需要在系统启动时自动执行某些命令&#xff0c;特别是需要 sudo权限的指令。为了实现这一功能&#xff0c;可以使用多种方法&#xff0c;包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法&#xff0c;并提供…...

解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错

出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上&#xff0c;所以报错&#xff0c;到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本&#xff0c;cu、torch、cp 的版本一定要对…...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)

文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...

在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案

这个问题我看其他博主也写了&#xff0c;要么要会员、要么写的乱七八糟。这里我整理一下&#xff0c;把问题说清楚并且给出代码&#xff0c;拿去用就行&#xff0c;照着葫芦画瓢。 问题 在继承QWebEngineView后&#xff0c;重写mousePressEvent或event函数无法捕获鼠标按下事…...