WPF 自定义控件中关于小数位数设置的改进之路
零、前言
我们在开发 WPF 程序的自定义控件时,会有显示或设置数值的需求,这样就难免会有能够自定义小数位数的需求,本文就是展示本人在其间不断改进的过程,希望能够抛砖引玉。
先进行基础设定,假设某个自定义控件中有一个 object 类型的 Value 依赖属性,可用来绑定数值类型,如果绑定的是浮点型,则引出了小数点位数自定义的需求场景。
一、StringFormat
将浮点数格式化显示为指定的小数位数,自然而然地就会想到 StringFormat(字符串格式化),它用于 Binding 中,可进行各种格式化,当要格式化小数位数时,形如:StringFormat='{}{0:F3}'
(3 位小数)。
我们当然可以在自定义控件的样式中使用 TextBlock 进行绑定,但是一来自定义控件没有 StringFormat 属性;二来 StringFormat 不是依赖属性,不能绑定,只能接受字符串;三来 StringFormat 是跟随着 Binding 的,无法单独在 Style 的 Setter 中进行设置;这三点相互羁绊,总而言之,这样就导致了 StringFormat 不太适合本次需求,不过也不是完全无药可治,咋们接着看。
使用 TextBlock 进行数值绑定还有个问题,比如外部绑定一个 float 的值时,在某种情况下不显示,改为 Label 则可以显示,当然这可能是受别的因素影响,但是不管怎么说,本次需求,TextBlock 已经半出局了,由 Label 取而代之。为什么说是半出局呢,因为本小节中,将会使用 Label + DataTemplate 的方式进行小数位数控制,而在 DataTemplate 中还是有 TextBlock 参与的,具体如下图(由于此方法并不是很好,就不再赘述了,感兴趣的朋友直接看图吧):
补充说明:
上图中使用了一个技术 —— 使用样式中的资源来简化样式的继承
也就是在 Style.Resources 中放置针对于 ControlTemplate 内某个或某几个元素的样式,然后在继承的样式中只需要提供另外的针对性样式即可:
二、ContentControl.ContentStringFormat
上一小节中我们让 TextBlock + StringFormat 半出局了,这一小节我们让它们完全出局,仅使用 Label。
由于 Label 没有 Text 属性,所以也不能用 StringFormat;它有 Content 属性,进行字符串格式化时需要使用 ContentStringFormat 属性。
Label 这一头解决了,那么自定义控件这边呢?答案就是使用 ContentControl.ContentStringFormat
进行设置:
ContentControl.ContentStringFormat 的定义如下:
三、自定义依赖属性 ContentStringFormat
上一节使用 ContentControl.ContentStringFormat 确实是可以的,不过我们既然是自定义控件了,还借用别人的依赖属性,多没面子呀,而且使用这个自定义控件的人也不一定知道可以用那个属性呀。所以更合适的方式就是,使用控件自己自定义的依赖属性 ContentStringFormat:
样式修改:
从上图中还可以看出之前使用 “使用样式中的资源来简化样式的继承” 技术实现的小数位数控制的痕迹,在一些场景下也是值得借鉴的。
四、使用样式触发器依据绑定的数据修改小数位数
本节接着上一节进行增强。
前面几节的小数位数控制都是写死的,那么能不能通过绑定,依据数据的情况自动改变小数位数呢?
我试过直接在 ContentStringFormat 的绑定字符串方面做手脚,但是可能是因为涉及格式化语法的原因,并没有成功,那么只能想其它方法曲线救国了。
方法就是在绑定的数据模型中增加一个 DecimalPlaces 这种属性(一般是 int 类型,或者更准确的 unit 类型),然后在样式触发器中,通过判断 DecimalPlaces 的值,自动设置 ContentStringFormat 的值,如下图所示:
大家还有什么其它好办法,欢迎不吝赐教。全文完。
原创文章,转载请注明: 转载自 独立观察员(dlgcy.com)
本文链接地址: [WPF 自定义控件中关于小数位数设置的改进之路](https://dlgcy.com/wpf-customcontrol-decimalplaces-by-contentstringformat/)
关注微信公众号 独立观察员博客(DLGCY_BLOG) 第一时间获取最新文章
发表评论