1. 从一次“乱码”的图表说起:LiveCharts的字体困境
最近在用C#的LiveCharts做数据可视化项目,给客户展示一个饼图,数据都准备好了,样式也调得差不多了,结果一运行,好家伙,图例和提示框里的中文全变成了一个个“小方框”或者乱码。这场景是不是很熟悉?我估计不少刚接触LiveCharts的C#开发者都踩过这个坑。你辛辛苦苦写好的MVVM架构,数据绑定流畅,逻辑清晰,结果最后卡在了这小小的字体显示上,确实让人有点泄气。
这个问题其实挺典型的。LiveCharts默认使用的是SkiaSharp进行图形渲染,这是一个跨平台的2D图形库,性能很强,但在处理中文字体时,如果没告诉它具体用哪个字体,它可能就“懵了”,找不到合适的字形来显示你的中文,于是就给你显示成乱码或者豆腐块(□)。这跟你用Word时,如果文档用了你电脑上没有的字体,打开也会显示异常是一个道理。
那为什么在MVVM模式下,这个问题解决起来需要一点特别的技巧呢?这就涉及到MVVM的核心思想了:视图(View)和视图模型(ViewModel)要解耦。我们当然可以直接在XAML里硬编码一个字体,但这不够“MVVM”。我们希望在ViewModel里能动态控制字体的样式、大小甚至颜色,比如根据用户主题切换深色/浅色模式时,自动调整图表的文字颜色。这时候,简单的静态设置就不够用了,我们需要一种方式,把字体这个“画笔”(Paint)也作为数据的一部分,从ViewModel“绑定”到View的图表控件上。这就是我们接下来要深入聊的,通过绑定 LegendTextPaint 和 TooltipTextPaint 这两个属性来根治中文乱码,并且让你的图表字体控制变得无比灵活。
2. 核心原理:为什么绑定“Paint”是解药
要理解这个解决方案,我们得先扒一扒LiveCharts的渲染机制。LiveCharts 2.x版本底层重度依赖SkiaSharp。在SkiaSharp的世界里,屏幕上画的任何文字,都不是简单的字符串,而是需要用一把“画笔”(SKPaint)蘸上“颜料”,按照特定的“字体”(SKTypeface)描绘出来的。SKPaint对象就封装了颜色、字体、字号、样式等所有绘制文本所需的属性。
在非MVVM的简单场景里,你可能会在代码后台直接创建一个SKPaint,指定一个中文字体文件路径,然后赋给图表。但这样做就把样式写死了,而且违背了MVVM的分离原则。MVVM模式下,我们的目标是:View只关心如何展示,ViewModel只关心展示什么和如何变化。字体的样式属于“如何变化”的范畴,理应归ViewModel管理。
LiveCharts的设计者显然考虑到了这一点。他们为图表的图例(Legend)和工具提示(Tooltip)暴露了LegendTextPaint和TooltipTextPaint这两个属性。这两个属性的类型是IPaint<SkiaSharpDrawingContext>,这是一个抽象,其背后的具体实现通常就是封装了SkiaSharp的SKPaint。关键在于,这两个属性支持数据绑定!这就为我们打开了大门。
我们可以把创建和配置SKPaint(特别是其中包含中文字体的SKTypeface)的逻辑放在ViewModel里。然后,将这个配置好的“画笔”对象,通过数据绑定传递给View层的图表控件。图表控件在渲染时,就会使用我们绑定的、包含了正确中文字体的画笔来绘制文字,乱码问题自然迎刃而解。同时,由于字体画笔是绑定来的,我们可以在ViewModel里随时修改它的颜色、大小,View上的图表会立即响应更新,实现了动态样式的控制。
3. 手把手实战:在MVVM项目中配置字体绑定
光说原理可能还有点抽象,我们直接上代码,一步步来。我假设你已经在WPF或类似的XAML框架中建立了一个基本的MVVM项目,并且通过NuGet安装了LiveChartsCore和LiveChartsCore.SkiaSharpView。
3.1 在ViewModel中创建并配置字体画笔
首先,打开你的ViewModel类(比如MainViewModel.cs)。我们需要在这里创建用于绑定的属性。
using LiveChartsCore;
using LiveChartsCore.SkiaSharpView.Painting;
using SkiaSharp;
p


776

被折叠的 条评论
为什么被折叠?



