简介
我目前有这样一个需求,在wpf开发的项目中使用echart绘图,echart作为基于javaScript的图表控件库,以网页的形式展现,在WPF中要使用该控件可以引入WPF浏览器控件 WEBBROWSER,实现echart于wpf的交互,wpf产生数据给echart绘图,在echart可以点击鼠标把相应的绘图信息传给wpf后台使用。
1.在窗体ReportWin(自己使用的窗体)想要显示图表的位置插入 WebBrowser ,代码如下所示:
2.引入echart
下载echart.js 添加至项目的路径下,点击显示所有文件按钮可以看到这个echart.js,右键鼠标-包括在项目中。 echart可到官网中下载。
3.在项目中添加一个html文件,在这个html文件实现chart绘图功能,新增一个chartPage.html
文件,代码如下:
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" http-equiv="X-UA-Compatible" content="IE=5,6,7,8,9,10,11, chrome=1" />
<title></title>
</head>
<body>
<h1>html页面</h1>
<div id="main" style="width:1000px;height:500px;margin-left:-8px" />
<script src="echarts.js"></script>
<script src="dark.js"></script>
<script src="jquery.js"></script>
<script>
plotChart = echarts.init(document.getElementById('main'));
option = {
xAxis: {
type: 'value',
axisLine: { onZero: false },
min: 0,
max: 30
},
yAxis: {
type: 'value',
axisLine: { onZero: false },
min: 0,
max: 60
},
series: [
{
data: [820, 932, 901, 934, 1290, 1330, 1320],
type: 'line'
},
{
data: [],
type: 'line',
// showSymbol: false,
//smooth: true,
lineStyle: {
normal: {
color: "lightgreen"
}
}
},
],
chartMode: 'overlap'
};
plotChart.setOption(option);
function jsDrawSE(data, index) {
option.series[index].data = JSON.parse(data);
plotChart.setOption(option);
}
function jsDrawNT(data) {
option.series[6].data = JSON.parse(data);
plotChart.setOption(option);
}
</script>
</body>
</html>
4.回到窗体的源文件中,窗体的构造函数添加如下:
public ReportWin()
{
InitializeComponent();
Web.Navigate(new Uri(System.IO.Directory.GetCurrentDirectory() + "\\chartPage.html"));
}
5.要实现WPF传送后台的数据给前端echart绘图,在这里我添加了一个绘图测试按钮用于测试绘图功能,数据用于测试没有实际含义。
首先要在脚本中定义绘图函数,步骤3的代码中已经添加该代码,wpf向前端传递数据并调用该函数绘图。
<script>
function jsDrawSE(data, index) {
option.series[index].data = JSON.parse(data);
plotChart.setOption(option);
}
</script>
///窗体类添加一个测试绘图按钮并添加鼠标点击事件,如下:
private void bt_plot_click(object sender, RoutedEventArgs e)
{
Task.Run(() =>//测试模拟后台输出文件
{
var sePoints1 = new double[20, 2];
for (int i = 0; i < 20; i++)
{
Thread.Sleep(2000);
sePoints1[i, 0] = i;
sePoints1[i, 1] = i * 1.2;
Console.WriteLine("do Taskwork,i={0}",i);
}
});
//Web.ObjectForScripting.
var sePoints = new double[20, 2];
for (int i = 0; i < 20; i++)
{
sePoints[i, 0] = i;
sePoints[i, 1] = i * 1.2;
}
Web.InvokeScript("jsDrawSE", JsonConvert.SerializeObject(sePoints), 1);
}
效果如下图所示
6.另外我需要与当前图表交互,比如当鼠标点击图表中的点时,想要获取当前点击的位置进行其他运算等。为了实现功能,我新增定义了一个ObjectForScriptingHelper类。
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
[ComVisible(true)]
public class ObjectForScriptingHelper
{
public int m_SeriesIndex { get; set; }
public int m_DataIndex { get; set; }
public int m_Data { get; set; }
public int m_Value{ get; set; }
public void TestInvoke(string data,string seriesIndex)
{
string[] strArray = data.Split(',');
m_Data = int.Parse(strArray[0]);
m_SeriesIndex = int.Parse(seriesIndex);
Console.WriteLine("data");
}
}
在web.Navigate之前添加如下代码
Web.ObjectForScripting = new ObjectForScriptingHelper(); //通过这个可以把winform中的变量传递到js中,类型必须是com可见;
7.首先引入jquery,在脚本中添加鼠标点击事件函数,要传出什么参数可以参考echart的api手册:events-鼠标事件,在 plotChart.setOption(option);之后添加如下鼠标点击事件:
plotChart.on('click', function (param) {
if (window.external === null)
alert('ObjectForScripting is not set');
else {
window.external.TestInvoke(param.data, param.seriesIndex);
}
});
echart鼠标点击事件参数
myChart.on('click', function(params) { console.log(params); });
代码执行,在鼠标点击图标的某个点时会进入测试函数,断点如下:
调试时发现只有点击鼠标的离散点才会进入前端的鼠标点击事件函数。