在WPF中嵌入WebBrowser可视化页面
程序员文章站
2022-04-28 19:30:09
无论是哪种C/S技术,涉及数据可视化就非常的累赘了,当然大神也一定有,只不过面向大多数人,还是通过网页来实现,有的时候不想把这两个功能分开,一般会是客户的原因,所以我们打算在WPF中嵌入WebBrowser,然后使用ECharts 完成复杂的图表展示,其功能不亚于一个名为Devexpress的图标库 ......
无论是哪种c/s技术,涉及数据可视化就非常的累赘了,当然大神也一定有,只不过面向大多数人,还是通过网页来实现,有的时候不想把这两个功能分开,一般会是客户的原因,所以我们打算在wpf中嵌入webbrowser,然后使用echarts 完成复杂的图表展示,其功能不亚于一个名为devexpress的图标库,而且这东西还收费(呵呵),本文就对webbrowser+echarts进行了演示。
首先下载一下echats.js文件以及jquery文件并且创建一个html页面,在我们项目的bin文件夹中。
在html中编辑,其中包括了几个方法,是对c#代码进行访问的。
<!doctype html> <html lang="zh-cn" xmlns="http://www.w3.org/1999/xhtml"> <!-- saved from url=(0013)about:internet --> <head> <meta charset="utf-8" http-equiv="x-ua-compatible" content="ie=5,6,7,8,9,10,11, chrome=1" /> <title>echarts</title> </head> <body> <h1>html页面</h1> <button onclick="click1()" style="width:100px;height:20px">测试</button> <script> function click1() { window.external.showmsg("这是一条信息"); } </script> <div id="main" style="width:1000px;height:500px;margin-left:-8px" /> <script src="echats.js"></script> <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script> <script> mychart = echarts.init(document.getelementbyid('main')); option = { xaxis: { type: 'category', data: ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun'] }, yaxis: { type: 'value' }, series: [{ data: [820, 932, 901, 934, 1290, 1330, 1320], type: 'line' }] }; mychart.setoption(option); </script> <script> function setoption(value) { var dataobj = json.parse(value);//将字符串转换为json对象 mychart.setoption(json.parse(dataobj));//将json对象转换为[object] } function jsshowhide(info) { if (info == 0) { mychart.clear(); } else { mychart.setoption(option); } } function jspushdata(x, y) { option.xaxis.data.push(x); option.series[0].data.push(y); mychart.setoption(option); } </script> </body> </html>
现在我们需要编辑一下我们的wpf窗体,在其中放入我们的浏览器,然后让它显示我们刚刚写好的页面。
<window x:class="eachartsdemo.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:local="clr-namespace:eachartsdemo" mc:ignorable="d" title="mainwindow" height="350" width="525" loaded="window_loaded"> <grid> <grid.rowdefinitions> <rowdefinition height="50"></rowdefinition> <rowdefinition></rowdefinition> <rowdefinition height="100"></rowdefinition> </grid.rowdefinitions> <textblock grid.row="0" text="webbrowser" horizontalalignment="center" verticalalignment="center" fontsize="25"></textblock> <webbrowser grid.row="1" name="web"></webbrowser> <stackpanel grid.row="2" orientation="horizontal" verticalalignment="center"> <textblock text="wpf按钮: " fontsize="20"></textblock> <button grid.row="2" name="btnshowhide" content="加载" click="btnshowhide_click"></button> <button grid.row="2" name="btnaddseries" content="追加" margin="10,0,0,0" click="btnpushdata_click"></button> <button grid.row="2" name="btnset" content="重置" margin="10,0,0,0" click="setoption"> </button> </stackpanel> </grid> </window>
在windows标记中我们需要一个load事件用于让webbrowser跳转到相应的页面。
private void window_loaded(object sender, routedeventargs e) { web.navigate(new uri(directory.getcurrentdirectory() + "/demo.html")); }
最后我们还需要创建几个方法,用于让c#直接调用其中js方法。
int show = 0; private void btnshowhide_click(object sender, routedeventargs e) { web.invokescript("jsshowhide", show); if (show == 0) show = 1; else show = 0; } private void btnpushdata_click(object sender, routedeventargs e) { web.invokescript("jspushdata", "x", 1000,"y","200"); } private void setoption(object sender, routedeventargs e) { string strobj = @"{""xaxis"":{""type"":""category"",""data"":[""mon"",""tue"",""wed"",""thu"",""fri"",""sat"",""sun""]},""yaxis"":{""type"":""value""},""series"":[{""data"":[100,200,300,400,500,600,700],""type"":""line""}]}"; var aa = jsonconvert.serializeobject(strobj.trim()); web.invokescript("setoption",aa); }
因为我们在xaml中把webbrowser的name改成了web,其中这个控件自带一个invokescript方法,就是来使用页面写好的function,就这样启动~
可见效果还可以,就现在我们要通过js调用c#方法,首先编辑一个页面可操作的类,我们创建 echatshelper ,必须在类上面标注特性,否则程序启动不起来,因为webbrowser是涉及一些安全性的东西,只要是在哪个类new出来,就必须在哪个类标注特性。
[permissionset(securityaction.demand, name = "fulltrust")] [system.runtime.interopservices.comvisible(true)]//给予权限并设置可见 public class echatshelper { webbrowser web; public echatshelper(webbrowser web) { this.web = web; } public void showmsg(string msg) { console.writeline(msg); } }
最后我们在load事件中创建应用程序对文档文件的寄宿脚本访问。
private void window_loaded(object sender, routedeventargs e) { web.objectforscripting = new echatshelper(web); web.navigate(new uri(directory.getcurrentdirectory() + "/demo.html")); }
就这样~我们测试一下~