[WPF]数据绑定时为何会出现StringFormat失效VPqCe7cCvg7iTH0g

news/2024/10/6 4:12:44

在数据绑定过程中,我们经常会使用StringFormat对要显示的数据进行格式化,以便获得更为直观的展示效果,但在某些情况下格式化操作并未生效,例如 ButtonContent属性以及ToolTip属性绑定数据进行StringFormat时是无效的。首先回顾一下StringFormat的基本用法。

StringFormat的用法

StringFormatBindingBase的属性,指定如果绑定值显示为字符串,应如何设置该绑定的格式。因此,BindingBase 的三个子类:BindingMultiBindingPriorityBinding都可以对绑定数据进行格式化。

Binding

Binding 是最常用的绑定方式,使用StringFormat遵循.Net格式字符串标准即可。例如:

或者

其中{0}表示第一个数值,如果 StringFormat 属性的值是以花括号开头,前边需要有一对花括号 {} 进行转义,也就是第一个例子中的 {}{0:C},否则不需要,如第二个示例一样。
如果设置 Converter 和 StringFormat属性,则首先将转换器应用于数据值,然后StringFormat 应用该值。

MultiBinding

Binding 绑定时,格式化只能指定一个参数,MultiBinding 绑定时则可指定多个参数。例如:

这个例子中 MultiBinding 是由多个子 Binding 组成,StringFormat 仅在设置 MultiBinding 时适用,子 Binding 中虽然也可以设置 StringFormat,但是会被忽略。

PriorityBinding

相比于前两种绑定,PriorityBinding 使用的频率没那么高,它的主要作用是按照一定优先级顺序设置绑定列表, 如果最高优先级绑定在处理时成功返回值,则无需处理列表中的其他绑定。 如果计算优先级最高的绑定需要很长时间,那么将会使用成功返回值的次高优先级,直到优先级较高的绑定成功返回值。PriorityBinding 和其包含的绑定列表中的子 Binding 也都可以设置 StringFormat 属性。例如:

MultiBinding 不同的是,PriorityBinding 的子 Binding中的 StringFormat是会生效的,其规则是优先使用子 Binding 设置的格式,其次才使用PriorityBinding 设置的格式。

Content属性格式化失效的原因

ButtonContent 属性可以用字符串赋值并显示在按钮上,但是使用 StringFormat 格式化并不会生效。原本我以为是涉及到类型转换器,在类型转换过程中处理掉了,但这只是猜测,通过源码发现并不是这样的。在 BindingExpressionBase 中有这样一段代码:

internal virtual bool AttachOverride(DependencyObject target, DependencyProperty dp)
{_targetElement = new WeakReference(target);_targetProperty = dp;DataBindEngine currentDataBindEngine = DataBindEngine.CurrentDataBindEngine;if (currentDataBindEngine == null || currentDataBindEngine.IsShutDown){return false;}_engine = currentDataBindEngine;DetermineEffectiveStringFormat();DetermineEffectiveTargetNullValue();DetermineEffectiveUpdateBehavior();DetermineEffectiveValidatesOnNotifyDataErrors();if (dp == TextBox.TextProperty && IsReflective && !IsInBindingExpressionCollection && target is TextBoxBase textBoxBase){textBoxBase.PreviewTextInput += OnPreviewTextInput;}if (TraceData.IsExtendedTraceEnabled(this, TraceDataLevel.Attach)){TraceData.TraceAndNotifyWithNoParameters(TraceEventType.Warning, TraceData.AttachExpression(TraceData.Identify(this), target.GetType().FullName, dp.Name, AvTrace.GetHashCodeHelper(target)), this);}return true;
}

其中第11行调用了一个名为 DetermineEffectiveStringFormat 的方法,顾名思义就是检测有效的 StringFormat。接下来看看里边的逻辑:

internal void DetermineEffectiveStringFormat()
{Type type = TargetProperty.PropertyType;if (type != typeof(string)){return;}string stringFormat = ParentBindingBase.StringFormat;for (BindingExpressionBase parentBindingExpressionBase = ParentBindingExpressionBase; parentBindingExpressionBase != null; parentBindingExpressionBase = parentBindingExpressionBase.ParentBindingExpressionBase){if (parentBindingExpressionBase is MultiBindingExpression){type = typeof(object);break;}if (stringFormat == null && parentBindingExpressionBase is PriorityBindingExpression){stringFormat = parentBindingExpressionBase.ParentBindingBase.StringFormat;}}if (type == typeof(string) && !string.IsNullOrEmpty(stringFormat)){SetValue(Feature.EffectiveStringFormat, Helper.GetEffectiveStringFormat(stringFormat), null);}
}

这段代码的作用就是检测有效的 StringFormat,并通过 SetValue 方法保存起来,从第4~7行代码可以看到,一开始就会检测目标属性的类型是不是 String 类型,不是的话直接返回,绑定表达式中的 StringFormat 也就不会保存了。在后续的 BindingExpression 类计算绑定表达式值时获取到 StringFormatnull,也就不会进行格式化了。
image:楚门加速器p

ButtonContent 属性虽然可以用字符串赋值,但它其实的 Object 类型。因此,在检测有效的 StringFormat 表达式时直接过滤了。ToolTip也同样是 Object 类型。
image

解决方法

对于 Content 这种 Object 类型的属性绑定字符串并且需要格式化时,可以采用以下三种方式解决:

  1. 最通用的方法就是自定义 ValueConverter,在 ValueConverter 中对字符串进行格式化;
  2. 绑定到其他可进行 StringFormat 的属性上,比如 TextBlockText 属性进行格式化,ToolTip 绑定到 Text 上;
  3. 既然是 Object 类型,那也可把 TextBlock 作为 Content的值。

小结

数据绑定时出现StringFormat失效的主要分为两种情况。一是没有遵循绑定时StringFormat使用的约束,二是绑定的目标属性不是 String 类型。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

容器 数据库 遛个弯

情境 参加了培训的第三次课, 本周内容的覆盖面有点广, 主要涉及docker概览, dvwa容器部署实验, 数据库CRUD, 以及某b**p软件的安装. 这里是第3课的作业题, 及我的解答.1、在docker中分别以后台方式和交互方式启动centos,对比启动后的容器状态,实现退出容器也能保持其运行状态…

nmap 主动探活

nmap 主动探活 当使用nmap探测主机时候,nmap会先发起主机活动测试,然后在执行相应的端口探测: 以下在 nmap 7.95 windows 和 nmap 7.8 debian测试 #仅使用-p8000测试,nmap会先执行主动探活然后再执行端口测试 nmap -p8000 110.242.68.4由上抓包可见,主动探测包括,ping(i…

一次失败的实验 - 无限注意力,我们为什么坚持实验

总结: 随着我们增加内存压缩次数的次数,Infini-attention 的性能会变得越来越差。据我们所知,ring attention、YaRN 和 rope scaling 这三种方法仍是将预训练模型拓展更长上下文的最佳方式。 引言: 语言模型的上下文长度也是除模型性能之外的重要属性之一。自 in-context lea…

VS Code 代码片段指南: 从基础到高级技巧

前言 “ 系列首发于公众号『非同质前端札记』 ,若不想错过更多精彩内容,请“星标”一下,敬请关注公众号最新消息。今天咱们来聊聊 VS Code 里的自定义代码片段。 这玩意儿简直是提升编码效率的神器, 用好了能让你敲代码更方便! 不管你是刚入行的菜鸟还是身经百战的老兵,这篇…

达梦数据库的备份与还原

参考:https://vip.kingdee.com/article/472067099301673728?lang=zh-CN&productLineId=29&isKnowledge=2功能简介 DM 数据库的备份还原包括两种类型:物理备份还原和逻辑备份还原。物理备份还原是对数据库的操作系统物理文件(如数据文件、控制文件和日志文件等)的备…

给一个块元素添加多张背景图片

最近做的项目需要用到多张底图(背景图) 最开始做的时候能想到的办法只有嵌套多层div然后设置背景图并定位以实现 今天重写这块代码发现明明可以很简单的解决!!! 话不多说,上代码<div class="menu"><!-- 任意内容 --> </div>先定义元素类名,…

情绪低落难释怀?数业智能心大陆用 AI 来破局

随着社会进步的步伐加快,人们生活节奏的日益紧张,心理健康问题越来越受到社会关注,其中,情绪调节更是心理健康的核心议题。数据显示,全球有数十亿人在不同程度上遭受着相关问题的困扰。在这样的大背景下,像数业智能这样依托先进 AI 技术的人工智能企业顺势而生,为提升用…

出海浪头之上,共探CDN进化新支力

CDN技术自问世以来已超过20个年头,在云计算与AI深度融合的大趋势下,各行业实际业务需求已发生巨变,下一代CDN技术又将走向何方?8月16日,“抓住泛娱热趋,打通增长脉络——大浪淘沙之后的CDN”技术沙龙活动在深圳圆满结束。阿里云专家与各企业代表,深入探索CDN技术变革之路…