当前位置: 首页 > news >正文

WPF基于LiveCharts2图形库,实现:折线图,柱状图,饼状图

WPF基于LiveCharts2图形库,实现:折线图,柱状图,饼状图

  • 使用流程
  • 创建工程
  • 安装LiveCharts2图形库
  • 解决中文乱码
  • 添加类文件
  • 运行效果

使用流程

1.安装LiveCharts2:NuGet包管理器搜索下载LiveChartsCore.SkiaSharpView.WPF
3.解决中文显示方框,添加LiveCharts.Configure(config => config.HasGlobalSKTypeface(SKFontManager.Default.MatchCharacter(‘汉’)));
4.添加名字空间声明xmlns:lvc=“clr-namespace:LiveChartsCore.SkiaSharpView.WPF;assembly=LiveChartsCore.SkiaSharpView.WPF”
5.创建视图基类
6.创建视图图表类
7.创建视图管理类
8.实例化视图图表类

创建工程

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

安装LiveCharts2图形库

在NuGet包管理器搜索LiveChartsCore.SkiaSharpView.WPF,一般要勾选“包括预发行版”
在这里插入图片描述

解决中文乱码

1.全局修改
在App.xaml.cs文件复写OnStartup方法,添加LiveCharts.Configure(config => config.HasGlobalSKTypeface(SKFontManager.Default.MatchCharacter(‘汉’)));

public partial class App : Application
{public static IHost? Host { get; private set; }protected override void OnStartup(StartupEventArgs e){// 设置全局中文字体LiveCharts.Configure(config => config.HasGlobalSKTypeface(SKFontManager.Default.MatchCharacter('汉')));base.OnStartup(e);}
}

2.局部修改(不影响其他模块)
在MainWindow.xaml.cs文件的构造方法里添加LiveCharts.Configure(config => config.HasGlobalSKTypeface(SKFontManager.Default.MatchCharacter(‘汉’)));

public MainWindow()
{// 设置中文LiveCharts.Configure(config => config.HasGlobalSKTypeface(SKFontManager.Default.MatchCharacter('汉')));InitializeComponent();
}            

在这里插入图片描述
实测验证两种方法均可解决中文显示方框的问题
在这里插入图片描述

添加类文件

图表视图基类:ChartBaseViewModel.cs

// ChartBaseViewModel.cs
using LiveChartsCore;
using System.ComponentModel;
using System.Runtime.CompilerServices;namespace LiveCharts2Demo
{public abstract class ChartBaseViewModel : INotifyPropertyChanged{public abstract ISeries[] Series { get; }public event PropertyChangedEventHandler PropertyChanged;protected virtual void OnPropertyChanged([CallerMemberName] string name = null){PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));}}
}

折线图视图类:LineChartViewModel.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;using LiveChartsCore;
using LiveChartsCore.SkiaSharpView;
using LiveChartsCore.SkiaSharpView.Painting;
using SkiaSharp;
using System.Collections.ObjectModel;
using System.ComponentModel;namespace LiveCharts2Demo
{public class LineChartViewModel : ChartBaseViewModel{private readonly ObservableCollection<double> _values;private readonly int _maxPoints;public override ISeries[] Series { get; }public LineChartViewModel(int maxPoints = 100){_maxPoints = maxPoints;_values = new ObservableCollection<double>();Series = new ISeries[]{new LineSeries<double>{Values = _values,Name = "随机数据",Stroke = new SolidColorPaint(SKColors.Blue, 2),Fill = null,GeometrySize = 0,LineSmoothness = 0.7,   // 折线平滑度 0 - 1}};}public void AddPoint(double value){_values.Add(value);while (_values.Count > _maxPoints)_values.RemoveAt(0);}public void Clear() => _values.Clear();}
}

柱状图视图类:BarChartViewModel.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;using LiveChartsCore;
using LiveChartsCore.SkiaSharpView;
using LiveChartsCore.SkiaSharpView.Painting;
using SkiaSharp;
using System.Collections.ObjectModel;
using System.ComponentModel;
using LiveChartsCore.Measure;namespace LiveCharts2Demo
{public class BarChartViewModel : ChartBaseViewModel{private readonly ObservableCollection<double> _values;public override ISeries[] Series { get; }// 可绑定到X轴标签public string[] Labels { get; set; }public Axis[] XAxes { get; set; }public Axis[] YAxes { get; set; }public BarChartViewModel(){_values = new ObservableCollection<double> {3, 6, 4, 8, 5};Labels = new[] { "A", "B", "C", "D", "E"};Series = new ISeries[]{new ColumnSeries<double>{Values = _values,Name = "测试数据",Stroke = new SolidColorPaint(SKColors.DarkSlateGray, 2),Fill = new SolidColorPaint(SKColors.CornflowerBlue)}};// 初始化 X 轴XAxes = new Axis[]{new Axis{Labels = Labels,LabelsRotation = -45, // 标签旋转角度Name = "分类"}};// 初始化 Y 轴YAxes = new Axis[] {new Axis{MinLimit = 0,MaxLimit = 20,Name = "数值",                    }};}/// <summary>/// 更新指定索引的值/// </summary>/// <param name="index"></param>/// <param name="value"></param>public void UpdateValue(int index, double value){if (index >= 0 && index < _values.Count){_values[index] = value;}else{_values.Add(value);// 动态扩展}}/// <summary>/// 随机动态更新(用于演示)/// </summary>public void RandomUpdate(){var rand = new Random();for (int i = 0; i < _values.Count; i++){UpdateValue(i, rand.Next(1, 10));}}}
}

饼状图视图类:PieChartViewModel.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;using LiveChartsCore;
using LiveChartsCore.SkiaSharpView;
using LiveChartsCore.SkiaSharpView.Painting;
using SkiaSharp;
using System.Collections.ObjectModel;
using System.ComponentModel;namespace LiveCharts2Demo
{public class PieChartViewModel : ChartBaseViewModel{private readonly ObservableCollection<double> _values;public override ISeries[] Series { get; }public PieChartViewModel(){_values = new ObservableCollection<double> { 3, 7, 5 };Series = new ISeries[]{new PieSeries<double>{Values = _values,  // 数据集合决定每个扇区的大小Name = "系列1",    // 系列名称,通常用于图例显示Fill = new SolidColorPaint(new SKColor(255, 99, 71)), // 设置扇区的颜色 番茄红Stroke = new SolidColorPaint(SKColors.Black, 1),  // 设置扇区边框的颜色和宽度DataLabelsPaint = new SolidColorPaint(SKColors.Red), // 设置数据标签文字的颜色                   InnerRadius = 0.5,  // 设置内半径为饼图的一半,从而形成环形图效果RelativeInnerRadius = 0.8,RelativeOuterRadius = 0.6,Pushout = 10,  // 当鼠标悬停在某个扇区上时,该扇区突出显示的距离HoverPushout = 5, // 鼠标悬停时额外推出的距离AnimationsSpeed = TimeSpan.FromMicroseconds(500),},new PieSeries<double>{Values = _values,Name = "系列2",Fill = new SolidColorPaint(new SKColor(54, 162, 235)), // 天蓝Stroke = new SolidColorPaint(SKColors.Black, 1),InnerRadius = 0.5,OuterRadiusOffset = 0.5,},new PieSeries<double>{Values = _values,Name = "系列3",Fill = new SolidColorPaint(SKColors.YellowGreen, 2),//Stroke = new SolidColorPaint(new SKColors.Blue, 1),//MaxOuterRadiusPercentage = 0.6}};}/// <summary>/// 更新第index个扇区的值/// </summary>/// <param name="index"></param>/// <param name="value"></param>public void UpdateSector(int index, double value){if (index >= 0 && index < _values.Count){_values[index] = value;}}public void RandomUpdate(){var rand = new Random();for (int i = 0; i < _values.Count; i++){UpdateSector(i, rand.Next(1, 10));}}}
}

视图管理:MainViewModel.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;namespace LiveCharts2Demo
{public class MainViewModel : INotifyPropertyChanged{public LineChartViewModel LineChart { get; } = new(100);public BarChartViewModel BarChart { get; } = new();public PieChartViewModel PieChart { get; } = new();public event PropertyChangedEventHandler PropertyChanged;protected virtual void OnPropertyChanged([CallerMemberName] string name = null){PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));}}
}

MainWindow.xaml

<Window x:Class="LiveCharts2Demo.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:lvc="clr-namespace:LiveChartsCore.SkiaSharpView.WPF;assembly=LiveChartsCore.SkiaSharpView.WPF"xmlns:local="clr-namespace:LiveCharts2Demo"mc:Ignorable="d"Title="MainWindow" Height="450" Width="800"><Window.DataContext><local:MainViewModel/></Window.DataContext><Grid><Grid.ColumnDefinitions><ColumnDefinition/><ColumnDefinition/></Grid.ColumnDefinitions><Grid.RowDefinitions><RowDefinition Height="*"/><RowDefinition Height="*"/><RowDefinition Height="*"/></Grid.RowDefinitions><!-- 折线图 --><lvc:CartesianChart Grid.Row="0" Grid.Column="0" Margin="10" Series="{Binding LineChart.Series}"/><!-- 柱状图 --><lvc:CartesianChartGrid.Row="0" Grid.Column="1"Margin="10" LegendPosition="Right" Series="{Binding BarChart.Series}"XAxes="{Binding BarChart.XAxes}"YAxes="{Binding BarChart.YAxes}"></lvc:CartesianChart><!-- 饼状图 --><lvc:PieChart Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2"LegendPosition="Bottom"Margin="10"                    Series="{Binding PieChart.Series}"/><StackPanel Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2"Orientation="Horizontal"HorizontalAlignment="Center"VerticalAlignment="Center"><Button Content="更新柱状图" x:Name="btnBarChartUpdate" Click="btnBarChartUpdate_Click" Margin="5"/><Button Content="更新饼状图" x:Name="btnPieChartUpdate" Click="btnPieChartUpdate_Click" Margin="5"/></StackPanel></Grid>
</Window>

MainWindow.cs

using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;using LiveChartsCore;
using LiveChartsCore.SkiaSharpView;
using LiveChartsCore.SkiaSharpView.Painting;
using LiveChartsCore.SkiaSharpView.WPF;
using LiveChartsCore.Measure;using SkiaSharp;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Threading;namespace LiveCharts2Demo
{/// <summary>/// Interaction logic for MainWindow.xaml/// </summary>public partial class MainWindow : Window{private readonly MainViewModel _vm;private readonly DispatcherTimer _timer;private double _phase = 0;public MainWindow(){// 设置全局字体-中文LiveCharts.Configure(config => config.HasGlobalSKTypeface(SKFontManager.Default.MatchCharacter('汉')));InitializeComponent();_vm = (MainViewModel)DataContext;// 模拟折线图动态数据更新_timer = new DispatcherTimer();_timer.Interval = TimeSpan.FromMilliseconds(200);_timer.Tick += (s, e) =>{//double value = Math.Sin(_phase) + (new Random().NextDouble() - 0.5) * 0.2;double value = (new Random().NextDouble()) * 100;_vm.LineChart.AddPoint(value);_phase += 0.5;};_timer.Start();}protected override void OnClosed(EventArgs e){_timer.Stop();base.OnClosed(e);}private void btnBarChartUpdate_Click(object sender, RoutedEventArgs e){_vm.BarChart.RandomUpdate();}private void btnPieChartUpdate_Click(object sender, RoutedEventArgs e){_vm.PieChart.RandomUpdate();}}
}

运行效果

请添加图片描述

http://www.dtcms.com/a/351510.html

相关文章:

  • 03. 协程入门_Android异步处理机制
  • 系统架构设计师备考第7天——网络协议中间件软件构件
  • WebSocket简单了解
  • 线性代数之深入理解旋转矩阵
  • lesson46-2:Linux 高级指令全解析:从文件操作到系统管理
  • mybatisplus 配置二级缓存
  • 【系统编程】线程简介
  • 【人工智能】2025年AI代理开源革命:社区驱动的智能体生态重塑未来
  • Linux--seLinux的概述
  • FRET、PLA、Co-IP和GST pull-down有何区别? 应该如何选择?
  • 原型模式系统开发中的原型分类全景:水平、垂直、抛弃式与演化式
  • nvm切换node版本之后报错,无法将“node”项识别为 cmdlet、函数、脚本文件或可运行程序的名称
  • 嵌入式C语言进阶:结构体封装函数的艺术与实践
  • IUV5G专网排障(上)
  • 支持向量机(SVM)学习笔记
  • SOME/IP服务发现PRS_SOMEIPSD_00277的解析
  • 服务器数据恢复—热备盘上线失败如何恢复数据?
  • 【Android】webview强制Crash后再自恢复设计
  • 服务器初始化
  • 影响服务器托管费用的因素​
  • ROS2 Helloworld 入门——包含完整pdf手册
  • Linux驱动开发笔记(九)——内核定时器
  • CSS 优先级:公司组织架构模型
  • css3背景线性渐变:linear-gradient
  • 基于Python+MySQL实现物联网引论课程一个火警报警及应急处理系统
  • 面向 6G 网络的 LLM 赋能物联网:架构、挑战与解决方案
  • 相机激光安全等级和人眼安全
  • 第九届MathorCup高校数学建模挑战赛-D题:钢水“脱氧合金化”配料方案的优化
  • 五自由度磁悬浮轴承同频振动抑制:从机理拆解到传递函数验证的核心方案
  • 【图像算法 - 24】基于深度学习与 OpenCV 实现人员跌倒识别系统(目标检测方案 - 跌倒即目标)