WPF依赖属性优先级

文章目录

  • 一、前言
  • 二、依赖属性优先级
    • 2.1 前置知识
    • 2.2 WPF属性系统
      • ⭐2.2.1 在多处设置依赖属性
    • ⭐2.3 依赖属性优先级列表
    • 2.4 模板的父亲/模板化父亲 TemplatedParent
    • 2.5 Style 属性
    • 🔺2.6 默认(主题)样式
    • 2.7 动态资源
    • 2.8 SetCurrentValue
    • 2.9 强制与动画
    • 2.10 触发器行为
    • 2.11 ClearValue
  • 三、总结

一、前言

在上篇文“依赖属性概述”中提到了依赖属性优先级,虽然知道了局部值具有高优先级,但是细节上略去太多。

这就导致了在实际遇到问题时,可能知道是优先级导致的,但不知道应该怎么处理。因此,有必要进一步学习。

原文地址

二、依赖属性优先级

WPF属性系统的工作方式会影响依赖属性的值。本文解释了WPF属性系统中不同的基于属性的输入的优先级是如何确定依赖属性的有效值的。

2.1 前置知识

本文假设你已具备依赖属性的基本知识。
如果还不知道什么是依赖属性,建议先看看上一篇文 “依赖属性概述” 。

2.2 WPF属性系统

WPF属性系统会根据各种因素来确定依赖属性的值,例如实时属性验证、延迟绑定以及相关属性的属性更改通知。
尽管确定依赖属性值的顺序和逻辑很复杂,但了解它们有助于你避免不必要的属性设置,和找出尝试设置依赖属性却没有得到预期值的原因。

要求程序员像机器(这边指WPF属性系统)一样,脑内运行这套逻辑显然不现实,但是了解这套系统的几个关键点,对实际项目中排查问题很有帮助。

⭐2.2.1 在多处设置依赖属性

下面XAML示例展示了按钮的 Background 属性上的三种不同的"设置"操作是如何影响其值的。

<StackPanel><StackPanel.Resources><ControlTemplate x:Key="ButtonTemplate" TargetType="{x:Type Button}"><Border Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderBrush}"><ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/></Border></ControlTemplate></StackPanel.Resources><Button Template="{StaticResource ButtonTemplate}" Background="red"><Button.Style><Style TargetType="{x:Type Button}"><Setter Property="Background" Value="Blue"/><Style.Triggers><Trigger Property="IsMouseOver" Value="True"><Setter Property="Background" Value="Yellow"/></Trigger></Style.Triggers></Style></Button.Style>Which color do you expect?</Button>
</StackPanel>

该例中, Background 属性(Button元素上的attribute和属性等价)被局部设置为 Red 。但是,在按钮作用域内声明的隐式样式尝试将 Background 属性设置为 Blue 。并且,当鼠标悬停在按钮上时,隐式样式中的触发器会尝试将 Background 属性设置为 Yellow 。除了强制值和动画外,局部设置属性值具有最高优先级,因此按钮将变成红色——即使在鼠标悬停时也是如此。但若你从按钮中删除局部设置的值,那么它将从样式中获取背景值。在样式中,触发器是优先的,因此鼠标悬停时按钮将为黄色,否则为蓝色。该示例替换了按钮的默认 ControlTemplate ,因为默认模板具有硬编码(hard-coded,即写死的固定值)的鼠标悬停背景值。

⭐2.3 依赖属性优先级列表

以下列表是属性系统在给依赖属性分配运行时值时所使用的明确优先级顺序。
越前面优先级越高。

  1. 属性系统强制 (Property system coercion)。
  2. 活动动画或具有保持行为的动画。为了有实际效果,动画值必须优先于基本值,即使基本值是局部的。
  3. 局部值。通过包装器属性设置局部值,相当于在XAML中设置attribute或属性元素,或者通过使用特定实例的属性调用SetValue API来设置局部值。 通过绑定或资源设置的局部值将与直接设置的值具有相同的优先级。
  4. TemplatedParent模板属性值。如果元素是由模板(ControlTemplate或DataTemplate)创建的,则该元素具有TemplatedParent。在TemplatedParent指定的模板中,优先级为:
    a. 触发器
    b. 通过XAML attribute的属性设置
  5. 隐式样式。仅适用于 Style 属性。Style 值是与元素类型匹配的TargetType值的任意样式资源。样式资源必须存在于页面或应用程序中。
    隐式样式资源的查找不会延申到主题中的样式资源。
  6. 样式触发器。样式触发器是显式或隐式样式内的触发器。该样式必须存在于页面或应用程序中。默认样式的触发器的优先级较低。
  7. 模板触发器。模板触发器是来自直接应用的模板,或样式内的模板的触发器。该样式必须存在于页面或应用程序中。
  8. 样式设置器值(setter)。样式设置器值是由样式内的Setter应用的值。样式必须存在于页面或应用程序中。
  9. 默认样式,也称为主题样式。默认样式中,优先顺序为:
    a. 活动的触发器
    b. 设置器
  10. 继承。子元素的某些依赖属性继承自其父元素。因此,一般没有必要在整个应用程序的每个元素上都设置属性值。
  11. 依赖属性元数据的默认值。依赖属性可以在该属性的属性系统注册期间设置默认值。继承依赖属性的派生类可以基于每个类型重写依赖属性元数据(包括默认值)。详细信息,参阅“依赖属性元数据”章节。对于继承的属性,父元素的默认值优先于子元素的默认值。因此,如果未设置可继承的属性,则使用根元素或父元素的默认值,而不是子元素的默认值。

2.4 模板的父亲/模板化父亲 TemplatedParent

TemplatedParent 优先级不适用于直接在标准应用程序标记中声明的元素的属性。 TemplatedParent 概念仅适用于通过应用程序模板而存在的可视化树中的子项。

可视化树
Visual Tree,即将文档页面上的控件进一步展开,进入其内部,是逻辑树的延申。
比如说页面上有一个按钮,逻辑树到按钮这一层就停止了,可视化树可以进到按钮内部,连里面有几个矩形,几个边框都知道。

①当属性系统在 TemplatedParent 指定的模板中搜索元素的属性值时,它实际上是在搜索创建该元素的模板。 ②TemplatedParent 模板中属性值通常表现为元素上的局部设置值,但优先级低于实际局部值,因为模板可能是共享的。

①持有模板的控件,搜索属性值要和一般控件区分开来;
②???

2.5 Style 属性

相同的优先级顺序适用于除了 Style 属性外的所有依赖属性。 Style 属性的独特之处在于它本身无法被样式化。不建议对 Style 属性进行强制或动画处理(而且对Style属性进行动画处理需要自定义动画类)。因此,并非所有优先级项都适用。设置 Style 属性只有三种方法:

  • 显式样式,元素的 Style 属性是直接设置的。 Style 属性值就像它的局部值一样,并且具有与优先级列表中的项3相同的优先级。大多数情况下,显式样式不是内联定义的,而是显式引用为资源,例如 Style="{StaticResource myResourceKey}"
  • 隐式样式,元素的 Style 属性不是直接设置的。相反,当样式存在于页面或应用程序中的某一级,并且具有与该样式所应用的元素类型匹配的资源键时,例如 <Style TargetType="x:Type Button">,该样式就会被应用。类型必须完全匹配,例如,即使 MyButton 派生自 Button<Style Target="x:Type Button"> 也不会应用于 MyButton 类型。 该 Style 属性值与优先级列表中的项5具有相同优先级。可以通过调用 DependencyPropertyHelper.GetValueSource 方法,传入 Style 属性并检查结果中的 ImplicitStyleReference 来检测隐式样式值。
  • 默认样式,也称为主题样式。其元素的 Style 属性也不是直接设置的。它来自WPF渲染引擎的运行时主题评估。在运行之前,Style 属性值为null。Style属性值与优先级列表中的项9具有相同的优先级。

🔺2.6 默认(主题)样式

WPF推出的每个控件都有一个默认样式,该样式可能因主题而异,这就默认样式有时也称为主题样式的原因。

ControlTemplate 是控件默认样式中的一个重要项,它是样式的Template属性的设置器值。如果默认样式不包含模板,则控件(应用了自定义样式,但样式中没有自定义模板的)将没有视觉外观。模板不仅定义控件的视觉外观,还定义了模板可视化树中的属性与相应控件类之间的连接。每个控件都公开一组属性,这些属性可以影响控件的视觉外观,而无需替换模板。例如,考虑Thumb控件的默认视觉外观,它是一个 ScrollBar 组件。(这个thumb不是点赞的拇指啊👍,指的是滑块控件)

Thumb 控件具有某些可自定义的属性。 Thumb 控件的默认模板创建一个基本结构和可视化树,并使用多个嵌套的 Border 组件来创建斜角外观。在模板内,想通过 Thumb 类修改的属性值可由 TemplateBinding 公开。 Thumb 控件的默认模板具有各种边框属性,这些属性与 BackgroundBorderThickness 等属性共享模板绑定。但是,如果属性或视觉排列的值在模板中是硬编码的,或者绑定到直接来自主题的值,则你只能通过替换整个模板来更改这些值。通常,如果属性来自模板化父亲并且未由 TemplateBinding 公开,则该属性值无法通过样式更改,因为没有便捷的方法来定位它。但是,该属性仍然会受到所应用模板中的属性值继承或默认值的影响。

默认样式在其定义中指定一个 TargetType 。运行时主题评估将默认样式的 TargetType 与控件的 DefaultStyleKey 属性相匹配。相反,隐式样式的查找行为使用控件的实际类型。 DefaultStyleKey 的值由派生类继承,因此可能没有关联样式的派生元素将获得默认的视觉外观。例如,如果从 Button 派生 MyButton ,则 MyButton 将继承 Button 的默认模板。派生类可以重写依赖属性元数据中 DefaultStyleKey 的默认值。因此,如果你希望 MyButton 具有不同的视觉表现形式,则可以重写 MyButtonDefaultStyleKey 的依赖属性元数据,然后定义相关的默认样式(包括模板),并将其与 MyButton 控件一起打包。

2.7 动态资源

动态资源引用和绑定操作具有它们设置位置的优先级。例如,应用于局部值的动态资源与优先级列表中的项3具有相同优先级;应用于默认样式内的属性设置器的动态资源绑定具有与优先级列表中的项9相同的优先级。由于动态资源引用和绑定必须从应用程序的运行时状态获取值,因此确定任何给定属性的属性值优先级都会延申到运行时。

从技术上讲,动态资源引用不是属性系统的一部分,并且具有自己的与优先级列表交互的查找顺序。本质上,动态资源引用的优先级时:到页面根目录的元素、应用程序、主题,然后是系统。

尽管动态资源引用和绑定具有其设置位置的优先级,但该值会被延迟。这样做的后果之一是,如果你将动态资源或绑定设置为局部值,则对局部值的任何更改都会完全替换动态资源或绑定。即使调用 ClearValue 方法清除局部设置值,动态资源或绑定也不会恢复。实际上,如果你对具有动态资源或绑定(没有文字局部值)的属性调用ClearValue,则动态资源或绑定将被清除(就不单单是清除值那么简单,是清除整个绑定)。

2.8 SetCurrentValue

SetCurrentValue 方法是设置属性的另一种方法,但它不在优先级列表中。 SetCurrentValue 允许你更改属性的值,而无需覆盖先前值的源。例如,如果某个属性由触发器设置,然后你使用 SetCurrentValue 分配另一个值,则下一个触发器操作会将该值设置回触发器值。每当你想要设置属性值而不为该值设定局部值的优先级时,都可以使用 SetCurrentValue 。同样,你可以使用 SetCurrentValue 更改属性的值,而无需覆盖绑定。

2.9 强制与动画

强制与动画都作用于基本值。基本值是具有最高优先级的依赖属性值,通过优先级列表向上计算直到第二项来确定。

如果动画没有为某些行为指定From和To属性值,或者动画在完成时有意恢复为基本值,则基本值能够影响动画值。

2.10 触发器行为

控件通常将触发行为定义为其默认样式的一部分。在控件上设置局部属性可能会与这些触发器发生冲突,从而阻止触发器响应(视觉上或行为上)用户驱动的事件。属性触发器的常见用途是控制状态属性,如 IsSelectedIsEnabled。例如,默认情况下,当禁用 Button 时,主题样式触发器(IsEnabled为false)会设置 Foreground值以使Button显示为灰色。如果你设置了局部 Foreground 值,则较高优先级的局部属性值会推翻主题样式的前景值,即使按钮处于禁用状态。当设置覆盖控件主题级别触发行为的属性值时,请注意不要过度干扰该控件的预期用户体验。

2.11 ClearValue

ClearValue方法清除元素的依赖属性的任何局部应用值。但是,调用 ClearValue并不能保证在属性注册期间在元数据中建立的默认值是新的有效值。优先级列表中的所有其他参与者仍然处于活动状态,并且仅删除本地设置的值。

三、总结

这章是相当复杂了,如果对WPF和依赖属性没有一定了解,看原文根本看不懂。
我觉得第一遍只要了解有优先级那么一回事儿,大致记一下设置属性的优先级顺序。
后面遇到具体问题再细细分析。

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

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

相关文章

【libwebrtc】基于m114

libwebrtc A C++ wrapper for binary release, mainly used for flutter-webrtc desktop (windows, linux, embedded).是 基于m114版本的webrtc 最新(20240309 ) 的是m122了。官方给出的构建过程 .gclient 文件 solutions = [{"name" : src,"url

微软AI工程师向联邦贸易委员会(FTC)发出警告,对Copilot Designer的安全性表示担忧

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

gitte上传项目操作

一、项目背景 打比赛&#xff0c;多个人合作&#xff0c;选择github&#xff0c;顺便了解下git的代码操作。 二、步骤 2.1 新建仓库 2.2 打开你要上传到库的项目 2.2 选择 Git Bash Here 输入指令 git init 2.3 查找github的仓库 2.2 将文件放入暂缓区 git add . 2.3填写…

LLM PreTraining from scratch -- 大模型从头开始预训练指北

最近做了一些大模型训练相关的训练相关的技术储备&#xff0c;在内部平台上完成了多机多卡的llm 预训练的尝试&#xff0c;具体的过程大致如下&#xff1a; 数据准备&#xff1a; 大语言模型的训练依赖于与之匹配的语料数据&#xff0c;在开源社区有一群人在自发的整理高质量的…

vue3 使用 mock 模拟服务器接口

文章目录 1. 安装相应的包2. 创建相关文件3. 构建请求 axios-mock-adapter 在前端开发中&#xff0c;需要模拟请求或者数据来做一些简单的调试&#xff0c;这里可以使用mock来模拟服务器接口&#xff1b; 1. 安装相应的包 这里需要安装两个包&#xff0c;一个是axios&#x…

jeecgboot 新建子模块 使用@EXCEL实现实现导入导出功能

一&#xff0c;用框架生成增删改查模块 二&#xff0c;在实体类entity 需要导入导出的字段上加上注解Excel 三&#xff0c;在controller类上继承jeecgboot通用controller JeecgController 并且在JeecgController里增加导出模板的方法 /*** 导出excel空模板** param req…

HTML:用对 preload、prefetch提升网页加载速度

在网页加载和数据获取方面&#xff0c;“preload” 和 “prefetch” 都是用来优化性能和用户体验的技术手段&#xff0c;但它们有一些区别。 Preload&#xff08;预加载&#xff09;&#xff1a; preload 用于指示浏览器在解析当前文档时预先加载指定资源&#xff08;如 CSS …

专业140+总430+电子科技大学858信号与系统考研经验成电电子信息与通信工程,电科大,真题,大纲,参考书。

今年考研成绩出来&#xff0c;初试专业课858信号与系统140&#xff0c;总分430&#xff0c;其余各门分数都比较平稳&#xff0c;总分好于自己估分&#xff0c;应群里很多同学要求&#xff0c;我总结一下自己的复习经验。首先我是一个大冤种&#xff0c;专业课资料学长给了一套&…

Linux select开发服务端

多路IO技术&#xff1a;select,同时监听多个文件描述符&#xff0c;将监控的操作交给内核去处理。 数据类型fd_set:文件描述符集合。 int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); 函数介绍&am…

态势感知的扭曲

态势感知中的扭曲是指由于各种原因导致对某些信息的感知出现偏差或错误的情况。扭曲可能是由于观察者的主观因素、信息来源的局限性、信息传递的失真等引起的。 在态势感知中&#xff0c;观察者的主观因素可能导致扭曲。例如&#xff0c;观察者的个人偏见、情绪状态、经验背景等…

5.53 BCC工具之dbslower.py解读

一,工具简介 dbstat用于追踪由MySQL或PostgreSQL数据库进程执行的查询,并显示查询延迟的直方图。 二,代码示例 #!/usr/bin/env pythonfrom bcc import BPF, USDT import argparse import subprocess from time import sleep, strftimeexamples = """dbsta…

挑战杯 基于深度学习的视频多目标跟踪实现

文章目录 1 前言2 先上成果3 多目标跟踪的两种方法3.1 方法13.2 方法2 4 Tracking By Detecting的跟踪过程4.1 存在的问题4.2 基于轨迹预测的跟踪方式 5 训练代码6 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于深度学习的视频多目标跟踪实现 …

软考高级:系统工程生命周期方法(计划驱动方法、渐进迭代式方法等)概念和例子

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;大厂高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

如何在Ubuntu系统部署DbGate数据库管理工具并结合cpolar内网穿透远程访问

文章目录 1. 安装Docker2. 使用Docker拉取DbGate镜像3. 创建并启动DbGate容器4. 本地连接测试5. 公网远程访问本地DbGate容器5.1 内网穿透工具安装5.2 创建远程连接公网地址5.3 使用固定公网地址远程访问 本文主要介绍如何在Linux Ubuntu系统中使用Docker部署DbGate数据库管理工…

web组态

演示地址 &#xff1a;by组态[web组态插件] 这是一款可以嵌入到任何项目组态插件&#xff0c;功能全面&#xff0c;可根据自己的项目需要进行二次开发&#xff0c;能大大的节省在组态上的开发时间&#xff0c;代码简单易懂。 一、数据流向图及嵌入原理 数据流向 嵌入原理 …

IPD是流程界的阳明先生

这个说法是不是很有趣呢&#xff01;IPD&#xff08;Integrated Product Development&#xff0c;集成产品开发&#xff09;是一种在产品开发领域广泛应用的流程方法&#xff0c;它强调跨职能团队的协作、迭代开发和以市场需求为导向的设计。 将 IPD 与阳明先生进行类比&#…

深度神经网络 基本知识 记录

资料&#xff1a;https://www.bilibili.com/video/BV1K94y1Z7wn/?spm_id_from333.337.search-card.all.click&vd_source14a476de9132ba6b2c3cbc2221750b99 计划&#xff1a;3~4天 注&#xff1a;网课讲的内容比较糅杂&#xff0c;记录的内容可能会出现重复 杂 人工智能…

c++ primer中文版第五版作业第十七章

仓库地址 文章目录 17.117.217.317.417.517.617.717.817.917.1017.1117.1217.1317.1417.1517.1617.1717.1817.1917.2017.2117.2217.2317.2417.2517.2617.2717.2817.2917.3017.3117.3217.3317.3417.3517.3617.3717.3817.39 17.1 tuple<int,int,int> it(10,20,30) 17.2 …

安全加速SCDN是服务器防御攻击较佳方案

国家互联网应急中心的数据研究显示&#xff0c;基于漏洞、病毒、未知威胁的攻击正日益频繁且智能化&#xff0c;网络安全的防护难度也与日俱增&#xff0c;未来应用层攻击将成为主流。互联网飞速发展之余&#xff0c;对于网络安全的需求也越来越大&#xff0c;网络攻击的手段也…

<商务世界>《第8课 Leads——MQL——SQL——商机——成交》

1 各种概念 英文缩写概念Traffic流量Leads潜在客户&#xff0c;销售线索&#xff1b;简称潜在线索MQLMarketing-Qualified Leads市场认可线索SQLSales-Qualified Leads销售认可线索OPPOpportunity商机Account成单客户 2 线索到商机 一般企业会把自身线索进行如下的划分&…