首页 > 其他分享 >[WPF]数据绑定时为何会出现StringFormat失效Nd

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

时间:2024-08-30 19:05:40浏览次数:13  
标签:格式化 parentBindingExpressionBase Nd 绑定 Binding StringFormat WPF 属性

在数据绑定过程中,我们经常会使用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:豆荚加速器

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

解决方法

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

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

    
        
    


小结

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

标签:格式化,parentBindingExpressionBase,Nd,绑定,Binding,StringFormat,WPF,属性
From: https://www.cnblogs.com/westworldss/p/18389356

相关文章

  • 关于vue render函数的写法
    vNode只是用来描述DOM,自身不维护状态,messageBox只是利用vNode渲染DOM,要想实现messageBox内容响应式,需要提供Vue实例(组件):写一个这样的组件新建组件(customRadioGroup.js):importVuefrom"vue";constCustomInput=Vue.component("CustomRadioGroup",{props:["value"......
  • [WPF]数据绑定时为何会出现StringFormat失效hC
    在数据绑定过程中,我们经常会使用StringFormat对要显示的数据进行格式化,以便获得更为直观的展示效果,但在某些情况下格式化操作并未生效,例如Button的Content属性以及ToolTip属性绑定数据进行StringFormat时是无效的。首先回顾一下StringFormat的基本用法。StringFormat的用法Str......
  • 2024-08-30 error [email protected]: The engine "node" is incompatible with this m
    删掉依赖,使用yarn重新拉取,保错如下:[email protected]:Theengine"node"isincompatiblewiththismodule.Expectedversion">=18".Got"16.19.1" 错误[email protected]:引擎“节点”与此模块不兼容。预期版本“>=18”。得到“16.19.1”意思就是yarn拉取依赖过程中......
  • g++链接报错:undefined reference to typeinfo of xxx
    g++链接报错:undefinedreferencetotypeinfoofxxx问题背景在项目中遇到了这样一个问题:C++文件编译都OK,但链接的时候报错:undefinedreferencetotypeinfoforxxx。std::typeinfo是C++中的RTTI(RunTimeTypeIdentification)机制中记录类型信息用的,dynamic_cast和typeid......
  • windows系统配置nginx环境运行pbootcms访问首页直接404的问题
    近来在协助客户处理安装过程中遭遇的这样一个状况,在安装pbootcms之后,访问后台的/admin.php能够成功,然而直接访问首页却显示404错误。运行环境所采用的运行环境为:windows操作系统加上nginx服务器再加上php语言的组合环境。详细经过客户表示伪静态规则始终未能生效,经过......
  • WPF DockPanel
    <Windowx:Class="WpfApp313.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft......
  • Google Trends使用教程详解
    GoogleTrends是谷歌旗下一款基于搜索数据推出的一款分析工具。它通过分析谷歌搜索引擎每天数十亿的搜索数据,告诉用户某一关键词或者话题各个时期下在谷歌搜索引擎中展示的频率及其相关统计数据。01进入谷歌趋势打开网址:https://trends.google.com/,输入关键词,点击Enter即......
  • 在Android开发中,如何使用SharedPreferences(简称SP)一个轻量级的数据存储方式
    目录全局SharedPreferences工具类代码说明:如何使用这个工具类?在Android开发中,SharedPreferences(简称SP)是一个轻量级的数据存储方式,常用于保存应用的配置信息或少量的数据。为了便于在全局使用,可以将其封装到一个工具类中。以下是一个带有详细中文注释的全局SharedPrefere......
  • Android的UI设计与布局
    目录Android布局系统概述常见的布局控件常见UI组件自适应布局和屏幕适配主题和样式 总结在Android中,UI设计与布局是开发过程中非常重要的一部分,直接决定了用户与应用的交互体验。Android提供了多种布局控件和UI组件,帮助开发者设计出不同风格和功能的界面。A......
  • ModuleNotFoundError: No module named ‘utils.query‘ flask项目遇到这种报错怎么解
    ModuleNotFoundError:Nomodulenamed'utils.query'这个错误表明你的Python代码正在尝试导入一个名为utils.query的模块,但未能成功找到它。以下是解决该问题的几个步骤:1.检查模块路径如果utils.query是你自己的模块或在项目中的某个目录下,确保文件路径正确。util......