赞
踩
毕业已经三年了,曾多次想记录在开发过程中遇到的一些问题,奈何一直觉得自己所知过于片面,故一直拖到今天才有勇气开始写自己的第一篇博客。此文中若有不正确的地方,望大家多多指正。
WPF无疑是很强大的,可以自己绘制各式各样的控件,当然也包括各类图表,笔者因水平有限,所以只能选择较为简单的方法,在WPF中嵌入ECharts图表,此处不对ECharts做介绍,下面简单介绍嵌入图表的三种方式:
下面从新建一个空的解决方案来逐步实现
(1)在ECharts官网或者GitHub下载对应的JS包
(2)将下载好的压缩包解压,并将dist文件夹复制到解决方案,设置为“复制到输出目录”,可删除不使用的JS。如下图所示
此节借鉴了ZaraNet博友的《使用CefSharp前端后台交换》在Nuget中添加对cefsharp.WPF引用,此时编辑项目是失败的,此处有两个解决办法,一是将项目平台改为x86或者x64版本,笔者改成x86版本是可以运行的,二是要使用AnyCpu,需要做如下修改
(1)App.xaml.cs中添加代码。
using CefSharp; using CefSharp.Wpf; using System; using System.Collections.Generic; using System.Configuration; using System.Data; using System.IO; using System.Linq; using System.Reflection; using System.Threading.Tasks; using System.Windows; namespace EchartRefSharpDemo { public partial class App : Application { private static void InitializeCefSharp() { var settings = new CefSettings(); // Set BrowserSubProcessPath based on app bitness at runtime settings.BrowserSubprocessPath = Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, Environment.Is64BitProcess ? "x64" : "x86", "CefSharp.BrowserSubprocess.exe"); // Make sure you set performDependencyCheck false Cef.Initialize(settings, performDependencyCheck: false, browserProcessHandler: null); } // Will attempt to load missing assembly from either x86 or x64 subdir // Required by CefSharp to load the unmanaged dependencies when running using AnyCPU private static Assembly Resolver(object sender, ResolveEventArgs args) { if (args.Name.StartsWith("CefSharp")) { string assemblyName = args.Name.Split(new[] { ',' }, 2)[0] + ".dll"; string archSpecificPath = Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, Environment.Is64BitProcess ? "x64" : "x86", assemblyName); return File.Exists(archSpecificPath) ? Assembly.LoadFile(archSpecificPath) : null; } return null; } } }
(2)编辑项目的配置文件也就是(*.csproj)文件,添加对AnyCpu支持的配置。
<CefSharpAnyCpuSupport>true</CefSharpAnyCpuSupport>
(3)还需添加X86平台,此处个人理解为,实际项目运行时还是x86形式,不过平台配置无需修改。配置步骤如下图。
此时编译项目,即可编译成功。
Cef和WebBrowser一样,提供了两种前后端交互的方式。
后端=>前端:ExecuteJavaScriptAsync:此方法在文中使用。
前端=>后端:BindObjectAsync:此方法的使用可参照前面提到的ZaraNet博友的文章。本文中暂未涉及。
<Window x:Class="EchartRefSharpDemo.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:hc="https://handyorg.github.io/handycontrol" mc:Ignorable="d" Title="MainWindow" WindowStartupLocation="CenterScreen" xmlns:cefSharp="clr-namespace:CefSharp.Wpf;assembly=CefSharp.Wpf" Height="450" Width="800"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="*"></RowDefinition> <RowDefinition Height="50"/> </Grid.RowDefinitions> <cefSharp:ChromiumWebBrowser Name="EchartWeb" FrameLoadEnd="EchartWeb_FrameLoadEnd"></cefSharp:ChromiumWebBrowser> <Button Grid.Row="1" Content="添加数据" Style="{StaticResource ButtonSuccess}" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75" Click="Button_Click"/> </Grid> </Window>
<!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml"> <head> <meta charset="utf-8"> <title>第一个 ECharts 实例</title> <script src="echarts.js"></script> <script src="echarts-min.js"></script> <!--<script src="jquery-3.1.1.js"></script>--> </head> <body> <!-- 为ECharts准备一个具备大小(宽高)的Dom --> <div id="main" style="width: 600px;height:400px;"></div> <script type="text/javascript"> //InitCodeData方法从MainWindow中进行调用。 function InitCodeData(listdata) { myChart = echarts.init(document.getElementById('main'), 'macarons'); //alert(listdata.Name); option = { title: { text: '动态折线图' }, tooltip: { trigger: 'axis', axisPointer: { type: 'cross', label: { backgroundColor: '#6a7985' } } }, legend: { data: ['XX数据'], }, //toolbox: { // feature: { // saveAsImage: {} // } //}, grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true }, xAxis: [ { type: 'category', boundaryGap: false, data: listdata.Name } ], yAxis: [ { type: 'value' } ], series: [ { name: 'XX数据', type: 'line', stack: '测试数据1', areaStyle: {}, data: listdata.Values }, ] }; myChart.setOption(option); } </script> </body> </html>
using System; using System.Collections.Generic; using System.IO; using System.Web.Script.Serialization; namespace EchartRefSharpDemo { public partial class MainWindow { #region Field int number = 20;//测试数据条数 #endregion Field public MainWindow() { InitializeComponent(); EchartWeb.Address = Directory.GetCurrentDirectory() + "/dist/LineChartDemo.html";//指定HTML地址 } /// <summary> /// 控件加载完成 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void EchartWeb_FrameLoadEnd(object sender, CefSharp.FrameLoadEndEventArgs e) { ChartData(number); } /// <summary> /// 测试按钮(模拟数据增加) /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Button_Click(object sender, System.Windows.RoutedEventArgs e) { number++; ChartData(number); } /// <summary> /// 调用Html中的方法,并传递模拟数据 /// </summary> /// <param name="y"></param> public void ChartData(int y) { DateTime dateTime = DateTime.Parse("2020-01-01"); ChartData listdata = new ChartData(); for (int i = 0; i < y; i++) { dateTime = dateTime.AddDays(1); listdata.Name.Add(dateTime.ToString("yyyy-MM-dd")); Random randomNum = new Random(Guid.NewGuid().GetHashCode()); listdata.Values.Add(randomNum.Next(0, 50)); } var jsons = new JavaScriptSerializer().Serialize(listdata); string js = $"InitCodeData({jsons});"; EchartWeb.GetBrowser().MainFrame.ExecuteJavaScriptAsync(js); } } /// <summary> /// 测试数据类 /// </summary> public class ChartData { public List<string> Name = new List<string>(); public List<int> Values = new List<int>(); //public string[] name=new string[5]; //public int[] values= new int[5]; //public Values value; } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。