[ASP.NET] Chart Control中的Series透過動態產生URL,值卻是零的問題

[ASP.NET] Chart Control中的Series透過動態產生URL,值卻是零的問題

最近在測試Chart Control的功能,發現Chart Control還滿智慧的,可以塞很多種資料型式,包含DataTable或是XML

 

只要將Series建立好以後,再透過指定Series的XValueMember以及YValueMembers以後

透過DataSource指派,並進行DataBind就可以產生圖片

 

原始的資料如下:

image

這邊假設這一份要繪成圖表的資料是說明著各個電腦產品的價格資訊。

Price代表定價,而UnitPrice代表單價,最後PPrice代表特價

 

看看以下的範例:

   1: //產生一個ChartControl
   2: Chart tChart1 = new Chart();
   3:        
   4: //新增ChartAreas
   5: tChart1.ChartAreas.Add(new ChartArea("CA"));
   6:  
   7: //建立新的Series,指定有三個Series
   8: tChart1.Series.Clear();
   9: tChart1.Series.Add("Price");
  10: tChart1.Series.Add("UnitPrice");
  11: tChart1.Series.Add("PPrice");
  12:  
  13: //指派每個Series的X軸與Y軸的成員
  14: tChart1.Series["Price"].XValueMember = "Product";
  15: tChart1.Series["Price"].YValueMembers = "Price";
  16:  
  17: tChart1.Series["UnitPrice"].XValueMember = "Product";
  18: tChart1.Series["UnitPrice"].YValueMembers = "UnitPrice";
  19:  
  20: tChart1.Series["PPrice"].XValueMember = "Product";
  21: tChart1.Series["PPrice"].YValueMembers = "PPrice";
  22:  
  23: //指定每個Series被點選時,要PostBack的值,若設為#VALX
  24: //則代表PostBack以後,事件會抓到指派為X成員的值
  25: tChart1.Series[0].PostBackValue = "#VALX";
  26: tChart1.Series[1].PostBackValue = "#VALX";
  27: tChart1.Series[2].PostBackValue = "#VALX";
  28:  
  29: //綁定Click事件,這邊透過ImageMapEventHandler來建立圖片的超連結
  30: //產生圖片互動的效果
  31: tChart1.Click += new ImageMapEventHandler(this.Chart_Click);
  32:  
  33: //先前都在定義圖片的結構,現在要正式的餵資料了
  34: //將DataSource指派為DataTable,並綁定資料(DataBind)
  35: tChart1.DataSource = myDataTable;
  36: tChart1.DataBind();
  37:  
  38: //在圖片還沒被產生以前,還可以針對各個Series進行設定
  39: foreach (Series tS in tChart1.Series)
  40: {
  41:    //圖表Series設定
  42:    tS.ChartType = SeriesChartType.Column;
  43:  
  44:    //識別是否為Pie,如果是則設定將內文拉出來
  45:    if (tS.ChartType == SeriesChartType.Pie)
  46:    {
  47:        tS["PieLabelStyle"] = "Outside";
  48:        tS["PieDrawingStyle"] = "Concave";
  49:        tChart1.Legends[0].Docking = Docking.Bottom;
  50:    }
  51:    if (tS.ChartType == SeriesChartType.Column)
  52:    {
  53:        tChart1.Legends.Add(new Legend());
  54:        tChart1.Legends[0].Docking = Docking.Top;
  55:        tChart1.ChartAreas[0].AxisX.IsLabelAutoFit = true;
  56:        tChart1.ChartAreas[0].AxisX.LabelStyle.Angle = 0;
  57:    }
  58: }
  59:  
  60: //將控件加到畫面中 
  61: this.Page.Form.Controls.Add(tChart1);

 

經由這樣的設定,我們可以產生下列的圖片,實在是方便又實惠

image

 

那麼有的時候我們會希望增加圖片的互動功能

因此可以看到上述的程式碼中,第25行到第27行就是在設定PostBackValue






再加上我們為ChartControl註冊Chart_Click的事件




以及定義事件:

   1: void Chart_Click(object sender, ImageMapEventArgs e)
   2: {
   3:     Response.Write(e.PostBackValue);
   4: }

 

 

透過這樣的設定,我們可以看到在點選圖片的時候會出現他已經幫我們綁定在事件的參數中了

image

 

因此我們點下那個伺服器的第一條Bar後,會PostBack到後端,並Response出伺服器的字樣

不過事情並不對勁,怎麼點下伺服器第的第二個Bar(橘色)跟第三個Bar(紅色)會出現0呢?(下方的URL)

imageimage

 

我們針對Series其實設定過三次,ChartControl自動幫整個DataTable的Row都產生出來。

不過Series中卻只有第一個Series才會正確地被產生參數超連結。

 

因此後來找到MSDN中就有問過這個問題  連結

 

“原因是因為當我們手動加入#VALX到Series的PostBack以後,後續加入的Series將會以Integer欄位的型態來識別來源欄位。”

 

他說僅有透過另一個方法來定義Series才能正確地產生X軸的值,而且這是一個Bug

將下列移除的程式碼,並換成關鍵的程式碼

   1: #region 移除
   2: tChart1.Series["Price"].XValueMember = "Product";
   3: tChart1.Series["Price"].YValueMembers = "Price";
   4:  
   5: tChart1.Series["UnitPrice"].XValueMember = "Product";
   6: tChart1.Series["UnitPrice"].YValueMembers = "UnitPrice";
   7:  
   8: tChart1.Series["PPrice"].XValueMember = "Product";
   9: tChart1.Series["PPrice"].YValueMembers = "PPrice";
  10: #endregion 
  11:  
  12: #region 關鍵
  13: foreach (DataRow drChart1 in myDataTable.Rows)
  14: {
  15:     tChart1.Series["Price"].Points.AddXY(drChart1["Product"], drChart1["Price"]);
  16:     tChart1.Series["UnitPrice"].Points.AddXY(drChart1["Product"], drChart1["UnitPrice"]);
  17:     tChart1.Series["PPrice"].Points.AddXY(drChart1["Product"], drChart1["PPrice"]);
  18: }
  19: #endregion

 

結果就能正常的將X軸的PostBack回去了!

image

 

 

參考資料:

http://social.msdn.microsoft.com/Forums/en/MSWinWebChart/thread/e6ebe90d-3340-4e61-b47b-0b7f4be7f683