当前位置: 代码网 > it编程>App开发>Windows Phone > WPF数据绑定时出现StringFormat失效的原因和解决方法

WPF数据绑定时出现StringFormat失效的原因和解决方法

2024年12月11日 Windows Phone 我要评论
前言在数据绑定过程中,我们经常会使用stringformat对要显示的数据进行格式化,以便获得更为直观的展示效果,但在某些情况下格式化操作并未生效,例如 button的 content属性以及tool

前言

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

首先回顾一下stringformat的基本用法。

stringformat的用法

stringformatbindingbase的属性,指定如果绑定值显示为字符串,应如何设置该绑定的格式。

因此,bindingbase 的三个子类:bindingmultibindingprioritybinding都可以对绑定数据进行格式化。

binding

binding 是最常用的绑定方式,使用stringformat遵循.net格式字符串标准即可。

例如:

<textblock text="{binding price,elementname=self,stringformat={}{0:c}}"/>

或者

<textblock text="{binding teststring,elementname=self,stringformat=test:{0}}"/>

其中{0}表示第一个数值,如果 stringformat 属性的值是以花括号开头,前边需要有一对花括号 {} 进行转义,也就是第一个例子中的 {}{0:c},否则不需要,如第二个示例一样。

如果设置 converterstringformat属性,则首先将转换器应用于数据值,然后stringformat 应用该值。

multibinding

binding 绑定时,格式化只能指定一个参数,multibinding 绑定时则可指定多个参数。

例如:

<textblock>
    <textblock.text>
        <multibinding stringformat="{}{0} {1}">
            <binding path="firstname" elementname="self"/>
            <binding path="lastname" elementname="self"/>
        </multibinding>
    </textblock.text>
</textblock>

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

prioritybinding

相比于前两种绑定,prioritybinding 使用的频率没那么高,它的主要作用是按照一定优先级顺序设置绑定列表, 如果最高优先级绑定在处理时成功返回值,则无需处理列表中的其他绑定。

如果计算优先级最高的绑定需要很长时间,那么将会使用成功返回值的次高优先级,直到优先级较高的绑定成功返回值。

prioritybinding 和其包含的绑定列表中的子 binding 也都可以设置 stringformat 属性。

例如:

<textblock
    width="100"
    horizontalalignment="center"
    background="honeydew">
    <textblock.text>
        <prioritybinding fallbackvalue="defaultvalue" stringformat="haha:{0}">
            <binding isasync="true" path="slowestdp" stringformat="hi:{0}"/>
            <binding isasync="true" path="slowerdp" />
            <binding path="fastdp" />
        </prioritybinding>
    </textblock.text>
</textblock>

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,也就不会进行格式化了。

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

解决方法

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

1、最通用的方法就是自定义 valueconverter,在 valueconverter 中对字符串进行格式化;

2、绑定到其他可进行 stringformat 的属性上,比如 textblocktext 属性进行格式化,tooltip 绑定到 text 上;

3、既然是 object 类型,那也可把 textblock 作为 content的值。

<button width="120" height="30">
    <button.content>
        <textblock text="{binding teststring,elementname=self,stringformat=test:{0}}"/>
    </button.content>
</button>

小结

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

最后

以上就是wpf数据绑定时出现stringformat失效的原因和解决方法的详细内容,更多关于wpf stringformat失效的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com