在WPF桌面系统需要实现仪表盘(dashboard是商业智能仪表盘(business intelligence dashboard,BI dashboard)的简称,它是一般商业智能都拥有的实现数据可视化的模块,是向企业展示度量信息和关键业务指标(KPI)现状的数据虚拟化工具。)形式的图表展示功能,研究了WPF开源的各个图件库,一般实现代码都比较复杂,灵活性不够,展示图表效果也不尽人意。后来想到ECharts,Echarts (ECharts)是百度公司出品的,算是百度不可多得的良心之作,使用方便灵活,而且支持各种基本的图表类型,如柱形图、折线图、饼图、条形图、面积图、散点图等等这些基本的图表类型等。
问题来了,ECharts是个前端JS库,只支持在页面上使用,要使用ECharts组件,可以在WPF窗体中Host一个WebBrowser控件,然后挂接本地运行目录的页面来实现。
步骤:
1、去ECharts官网下载ECharts库和相关示例 页面,复制到exe运行文件目录中。
2、创建一个WPF项目,增加一个View类。因为WebBrowser控件是个Windows Form控件,WPF窗体不能直接运行WinForm控件,然后在WPF窗体上添加WindowsFormsHost控件,此WindowsFormsHost控件可作为Win From控件运行的容器。
在WPF窗体头部引入 WebBrowser控件命名空间, xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
<Grid>
<WindowsFormsHost HorizontalAlignment="Stretch" Margin="15,0,15,5" x:Name="wfHost">
<wf:WebBrowser x:Name="webBrowser" Url="" DocumentCompleted="webBrowser_DocumentCompleted" SizeChanged="webBrowser_SizeChanged"></wf:WebBrowser>
</WindowsFormsHost>
</Grid>
然后定义事件,在页面装载完成后执行JS脚本,展示图表:
private void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
Object[] objArray = new Object[1];
objArray[0] = (Object)this.option;
this.webBrowser.Document.InvokeScript("showChart", objArray);
objArray[0] = (Object)this.Height;
this.webBrowser.Document.InvokeScript("setPosition", objArray);
blnDocumentLoaded = true;
}
窗体控件具体代码如下:
[System.Runtime.InteropServices.ComVisibleAttribute(true)]
public partial class EChartView : ShellViewBase
{
public EChartView()
{
InitializeComponent();
}
public object option { get; set; }
private bool blnDocumentLoaded = false;
private bool blnDynamicData = false;
public string param;
[Category("echarts"), Description("Get DBClick return params.nGet DBClick return params")]
private string strParam
{
get { return param; }
set
{
param = value;
if (DbClickReturnParam != null)
{
DbClickReturnParam(this);
}
}
}
public void initialECharts(int type)
{
if (blnDocumentLoaded)
{
Object[] objArray = new Object[1];
objArray[0] = (Object)this.option;
if (type == 1001)
{
this.webBrowser.Document.InvokeScript("showDynamic", objArray);
}
else if (type == 10)
{
this.webBrowser.Document.InvokeScript("showBar10", objArray);
}
else
{
this.webBrowser.Document.InvokeScript("showChart", objArray);
}
}
else
{
string folder = LoadApplicationPath();
string strHtml = folder + @"assetsecharts.html";
if (File.Exists(strHtml))
{
this.webBrowser.Navigate(strHtml);
this.webBrowser.ObjectForScripting = this;
}
}
}
private void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
Object[] objArray = new Object[1];
objArray[0] = (Object)this.option;
this.webBrowser.Document.InvokeScript("showChart", objArray);
objArray[0] = (Object)this.Height;
this.webBrowser.Document.InvokeScript("setPosition", objArray);
blnDocumentLoaded = true;
}
private void webBrowser_SizeChanged(object sender, EventArgs e)
{
if (blnDocumentLoaded)
{
Object[] objArray = new Object[1];
objArray[0] = (Object)this.Height;
this.webBrowser.Document.InvokeScript("setPosition", objArray);
}
}
public void showDetail(string strJsRetunedParam)
{
strParam = JsonConvert.SerializeObject((object)JsonConvert.DeserializeObject(strJsRetunedParam, typeof(echartsParam)));
}
private static string LoadApplicationPath()
{
return System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
}
public delegate void DbClickHandle(object sender);
public event DbClickHandle DbClickReturnParam;
}
}
public class echartsOption
{
public struct optionTitle
{
public string text { get; set; }
public string subtext { get; set; }
}
public optionTitle title;
public struct optionTooltip
{
public string trigger { get; set; }
}
public optionTooltip tooltip;
public struct optionLegend
{
public bool selectedMode { get; set; }
public ArrayList data { get; set; }
}
public optionLegend legend;
public struct optionToolbox
{
public bool show { get; set; }
public struct optionToolboxFeature
{
public struct optionToolboxFeatureMark
{
public bool show { get; set; }
}
public optionToolboxFeatureMark mark;
public struct optionToolboxFeatureDataView
{
public bool show { get; set; }
}
public optionToolboxFeatureDataView dataView;
public struct optionToolboxFeatureMagicType
{
public bool show { get; set; }
public ArrayList type { get; set; }
}
public optionToolboxFeatureMagicType magicType;
public struct optionToolboxFeatureRestore
{
public bool show { get; set; }
}
public optionToolboxFeatureRestore restore;
public struct optionToolboxFeatureSaveAsImage
{
public bool show { get; set; }
}
public optionToolboxFeatureSaveAsImage saveAsImage;
}
public optionToolboxFeature feature;
}
public optionToolbox toolbox;
public bool calculable { get; set; }
public struct optionXAxis
{
public string type { get; set; }
public ArrayList data { get; set; }
}
public optionXAxis[] xAxis;
public struct optionYAxis
{
public string type { get; set; }
}
public optionYAxis[] yAxis;
public struct optionSeries
{
public string name { get; set; }
public string type { get; set; }
public ArrayList data { get; set; }
}
public optionSeries[] series;
}
public class echartsParam
{
public string data { get; set; }
public int dataIndex { get; set; }
public string name { get; set; }
public int seriesIndex { get; set; }
public string seriesName { get; set; }
public string type { get; set; }
public string value { get; set; }
}
增加类echartsParam和echartOption来使用和控制echarts参数。
3、使用ECharts包装的控件在WPF窗体中展示图表,使用起来非常简单,把控件放到需要展示图表的窗体中,在EyChartView_Initialized方法中并把参数传递给图表控件来控制图表的样式、大小及数据内容等 。
<ScrollViewer x:Name="tileScrollViewer" Grid.Row="0" Grid.Column="1" Height="485" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Hidden" Mouse.PreviewMouseWheel="ScrollViewer_PreviewMouseWheel">
<Grid >
<echart:EChartView x:Name="echartView" Initialized="EChartView_Initialized" Loaded="EChartView_Loaded" ></echart:EChartView>
</Grid>
</ScrollViewer>
private void EChartView_Loaded(object sender, RoutedEventArgs e)
{
echartsOption eoption = new echartsOption();
eoption.title.text = "Demo";
eoption.tooltip.trigger = "item";
eoption.legend.data = new ArrayList();
eoption.legend.data.Add("Actual");
eoption.legend.data.Add("Balance");
eoption.toolbox.show = true;
eoption.toolbox.feature.magicType.show = true;
eoption.toolbox.feature.magicType.type = new ArrayList();
eoption.toolbox.feature.magicType.type.Add("line");
eoption.toolbox.feature.magicType.type.Add("bar");
eoption.toolbox.feature.restore.show = true;
eoption.xAxis = new echartsOption.optionXAxis[1];
eoption.xAxis[0].type = "category";
eoption.xAxis[0].data = new ArrayList();
eoption.xAxis[0].data.Add("Jan");
eoption.xAxis[0].data.Add("Feb");
eoption.xAxis[0].data.Add("Mar");
eoption.xAxis[0].data.Add("Apr");
eoption.xAxis[0].data.Add("May");
eoption.xAxis[0].data.Add("Jun");
eoption.xAxis[0].data.Add("Jul");
eoption.xAxis[0].data.Add("Aug");
eoption.xAxis[0].data.Add("Sep");
eoption.xAxis[0].data.Add("Oct");
eoption.xAxis[0].data.Add("Nov");
eoption.xAxis[0].data.Add("Dec");
eoption.yAxis = new echartsOption.optionYAxis[1];
eoption.yAxis[0].type = "value";
eoption.series = new echartsOption.optionSeries[2];
eoption.series[0].name = "Actual";
eoption.series[0].type = "bar";
eoption.series[0].data = new ArrayList();
eoption.series[0].data.Add(1);
eoption.series[0].data.Add(2);
eoption.series[0].data.Add(3);
eoption.series[0].data.Add(4);
eoption.series[0].data.Add(5);
eoption.series[0].data.Add(6);
eoption.series[0].data.Add(7);
eoption.series[0].data.Add(8);
eoption.series[0].data.Add(9);
eoption.series[0].data.Add(10);
eoption.series[0].data.Add(11);
eoption.series[0].data.Add(12);
//
eoption.series[1].name = "Balance";
eoption.series[1].type = "bar";
eoption.series[1].data = new ArrayList();
eoption.series[1].data.Add(12);
eoption.series[1].data.Add(11);
eoption.series[1].data.Add(10);
eoption.series[1].data.Add(9);
eoption.series[1].data.Add(8);
eoption.series[1].data.Add(7);
eoption.series[1].data.Add(6);
eoption.series[1].data.Add(5);
eoption.series[1].data.Add(4);
eoption.series[1].data.Add(3);
eoption.series[1].data.Add(2);
eoption.series[1].data.Add(1);
//
this.echartView.option = JsonConvert.SerializeObject(eoption);
echartView.initialECharts(0);
4、运行查看效果