將數據庫數據提取出來,顯示成曲線圖(餅狀、柱狀或立體圖)是項目中最常見的需求。 網上搜索到的解決方法,大多歸為兩類,一種是利用ActiveX組件,另一種是使用.Net框架自帶的畫圖的類。前者開發比較方便,但浏覽時需要用戶下載ActiveX插件(而這個往往是忌諱的,插件帶毒)。後者,需要你自己寫繪圖、生成圖片的類庫,不過在開源社區已有不少的項目針對這個問題,做出了實現。ZedGraph是其中之一,網上的評論大多如是說:使用方便,易上手。
ZedGraph是c#編寫的類庫,提供了用戶控件和web控件。官網的例子提供了在Windows窗體上顯示圖片的源碼,而如何將它應用到web項目中,卻沒有任何介紹(或許是我沒找到),web控件才是項目中有價值的東東。一番搜索後,摟到了一些實現,確實!它已經封裝到相當優秀的程度,舉個例子:
我們在畫曲線圖的時候,往往為如何設計X、Y軸的坐標而頭疼,如何設置它數值范圍、設置單元間距等,才能讓我們的數據顯示得盡量完整和精確。而它的設計是,只要你提供數據,X/Y軸的問題不用管——它會找出數據范圍,然後設置合理的顯示域和單元間距。下面是一個簡單的實現,將數據庫數據生成一張曲線圖和柱狀圖,如此它便可以被這樣的方式,顯示到頁面上:
<body>
<img src="Pic.ASPx">
</body>
首先,你需要將兩個dll引用至你的工程,ZedGraph.dll和ZedGraph.web.dll。接下來,是你要生成圖片的頁面,暫且命名為pic.ASPx,將它的Html標簽部分去掉,添加ZEDGRAPHWEB控件:
<%@ Page language="c#" Codebehind="PriceTimePic.ASPx.cs" AutoEventWireup="false"
Inherits="Herbalife.HelpDesk.UI.ReportManage.PurchaseReport.PriceTimePic" %>
<%@ Register TagPrefix="zgw" Namespace="ZedGraph.Web" Assembly="ZedGraph.Web"%>
<ZGW:ZEDGRAPHWEB id="ZG" runat="server" width="500" Height="375" RenderMode="RawImage" />
然後,我們到pic.ASPx.cs下,添加包引用:using ZedGraph; using ZedGraph.Web;,添加控件對象的聲明:protected ZedGraph.Web.ZedGraphWeb ZG;。接下來在InitializeComponent()方法中注冊一個事件:
// OnRenderGraph 繪圖方法
this.ZG.RenderGraph += new ZedGraph.Web.ZedGraphWebControlEventHandler(this.OnRenderGraph);
下面便是繪圖方法了:
private void OnRenderGraph(System.Drawing.Graphics g, ZedGraph.MasterPane masterPane)
{
GraPHPane myPane = masterPane[0];
// Title
myPane.Title.Text = "供應商 價格-時間曲線圖";
myPane.XAxis.Title.Text = "時間";
myPane.YAxis.Title.Text = "價格";
// 坐標對集合
PointPairList line = new PointPairList();
// 取數據部分
DataTable dt = GetData();
// 將數據轉為(X,Y)坐標對
for(int i=0;i<dt.Rows.Count;i++)
{
/*
* 添加坐標對,需要將X/Y值全部轉為double類型。原本以為他們會支持DateTime類型。
* 個人覺得還是很有必要的,畢竟很多圖都是時間-**曲線圖,有需求。
*/
string date = Convert.ToDateTime(dt.Rows[i]["RecTime"]).ToString("yyyyMMdd");
line.Add(Convert.ToDouble(date), Convert.ToDouble(dt.Rows[i]["Price"]));
}
// 繪制曲線
LineItem li = myPane.AddCurve("aaa",line, Color.Blue);
masterPane.AxisChange(g);
}
效果圖如下:
由於日期類型轉換成double型,結果X軸還是比較難看的。目前正在研究它的類庫,應該可以更改的。
餅狀圖,則需要修改OnRenderGraph方法:
private void OnRenderGraph(System.Drawing.Graphics g, ZedGraph.MasterPane masterPane)
{
GraPHPane myPane = masterPane[0];
// Title
myPane.Title.Text = "供應商 價格-時間曲線圖";
myPane.XAxis.Title.Text = "時間";
myPane.YAxis.Title.Text = "價格";
// 坐標對集
PointPairList line = new PointPairList();
DataTable dt = GetData();
for(int i=0;i<dt.Rows.Count;i++)
{
string date = Convert.ToDateTime(dt.Rows[i]["RecTime"]).ToString("yyyyMMdd");
line.Add(Convert.ToDouble(date), Convert.ToDouble(dt.Rows[i]["Price"]));
}
BarItem myCurve = myPane.AddBar("aaa", line, Color.Blue);
myCurve.Bar.Fill = new Fill(Color.Blue, Color.White, Color.Blue);
myPane.XAxis.MajorTic.IsBetweenLabels = true;
// X軸Label
string[] labels = new string[dt.Rows.Count];
for(int i=0;i<dt.Rows.Count;i++)
ls[i] = Convert.ToDateTime(dt.Rows[i]["RecTime"]).ToString("yyyy/MM/dd");
myPane.XAxis.Scale.TextLabels = labels;
myPane.XAxis.Type = AxisType.Text;
// 顏色填充
myPane.Fill = new Fill(Color.White, Color.FromArgb(200, 200, 255), 45.0f);
myPane.Chart.Fill = new Fill(Color.White, Color.LightGoldenrodYellow, 45.0f);
masterPane.AxisChange(g);
}
效果圖: