Microsoft Chart Controls 心得(2) - 如何透過圖表傳值

利用MS Chart來製作可以回傳數值的圖表,已提供User下一步的動作

使用圖表進行說明時最常做的當然是圖表內容的分析說明,不過在進行分析說明的時候可能需要利用很多種不同類型的圖型來進行展展示. 例如使用大餅圖來說明目前各種類所佔的百分比再使用線圖或是另一張大餅圖來展示單獨種類分佈的情況.

下面我就來做一個Sample來跟大家分享一下如何使用MS Chart + Ajax .Net 做到這種功能

  1. 事前準備
    圖表資料來源的部分,這次我採用sql server 2005 expres
    新增兩張Table並填入對應的資料
    Chart_2_1
     
  2. 設定顯示畫面
    使用Button、Chart、UpdatePanel幾個控制項產生下列畫面
    Chart_2_2

    Code:
    <body>
        <form id="form1" runat="server">
        <div>
            <asp:ScriptManager ID="ScriptManager1" runat="server">
            </asp:ScriptManager>
            <table style="border:solid 1px #000000;">
                <tr>
                    <td align="left" colspan="2">
                        <asp:Button ID="Button1" runat="server" onclick="Button1_Click" Text="查詢" />
                        <hr />
                    </td>
                </tr>
                <tr>
                    <td align="center" style="width:450px;">
                        <asp:Chart ID="Chart1" runat="server" Height="400px" Width="400px" 
                            onclick="Chart1_Click">                
                        </asp:Chart>
                    </td>
                    <td align="center">
                        <asp:UpdatePanel ID="UpdatePanel1" runat="server">
                            <ContentTemplate>
                                <asp:Chart ID="Chart2" runat="server" Height="400px" Width="400px">
                                </asp:Chart>
                            </ContentTemplate>
                            <Triggers>
                                <asp:AsyncPostBackTrigger ControlID="Chart1" />
                            </Triggers>
                        </asp:UpdatePanel>
                    </td>
                </tr>
            </table>
        </div>
        </form>
    </body>

    這邊稍微說明一下UpdatePanel的部分,我相信很多人應該都很會使用這個控制項.因為我曾經聽過有人說只要把整張頁面放進去UpdatePanel裡面,就可以達成Ajax的效果,關於這點..我也不知道該怎麼說,去除掉他的一些限制,外加不理會效能的話,算是對的吧! 不過在這邊還是建議大家使用在該用的地方就好了.

    這邊我設定了兩個Chart,透過Chart1的Click事件來觸發UpdatePanel進行Chart2的繪製,UpdatePanel可以設定多組的trigger,這部份大家可以多多利用.

  3. 撰寫 Server 端程式碼
    • 繪製 Chart1
      try
      {
          #region Step1. 設定 Chart Title
          Title ChartTitle = new Title();
          System.Drawing.Font font = new System.Drawing.Font("標楷體", 20);
          ChartTitle.Font = font;
          ChartTitle.ForeColor = System.Drawing.ColorTranslator.FromHtml("#6B8E23");
          ChartTitle.Text = "Sample圖表";
          //新增至Chart Control
          Chart1.Titles.Add(ChartTitle);
          #endregion
      
          #region Step2. 產生工作區塊(Area1)
          ChartArea cArea1 = new ChartArea("Area1");
          cArea1.Area3DStyle.Enable3D = true;
      
          Series series1 = new Series("");
      
          series1.ChartArea = "Area1";
          series1.ChartType = SeriesChartType.Pie;
          series1.IsValueShownAsLabel = true;
      
          #region 填入資料
          using (DBObj oDB = new DBObj())
          {
              var DBData = from o in oDB.Product
                           join p in
                               (
                                 from p1 in oDB.SaleDetail
                                 where p1.Year == "2008"
                                 select p1
                               ) on o.No equals p.ProductNo into C
                           select new
                           {
                               o.No,
                               o.Product1,
                               T = C.Count(),
                               T1 = ((float?)C.Count() / (float?)oDB.SaleDetail.Count(pp => pp.Year == "2008")) * 100
                           };
      
              foreach (var tmp in DBData)
              {
                  series1.Points.AddXY(tmp.Product1, String.Format("{0:F2}", tmp.T1));
      
              }
          }
          #endregion
      
          series1.PostBackValue = "#AXISLABEL";
          series1.ToolTip = "產品 : #AXISLABEL";
          #endregion
      
          Legend leg = new Legend("分類");
          leg.Docking = Docking.Right;
          Chart1.Legends.Add(leg);
      
          Chart1.ChartAreas.Add(cArea1);
          Chart1.Series.Add(series1);
      }
      catch (Exception ex)
      {
          System.Web.UI.ScriptManager.RegisterStartupScript(Page, Page.GetType(), "Exception", " var s= alert('" + ex.Message.ToString().Replace("'", "").Replace("\"", "") + "')", true);
      }
      


      裡面最重要的是下列這一個部份

      首先要設定圖型被點選時該DataPoint要回傳的值是什麼
      series1.PostBackValue = "#AXISLABEL";
      由於一直找不到MS Chart關於這部份的說明,如果有人找到麻煩跟我分享一下吧
      後來使用SSRS的寫法試試看,既然是微軟的東西應該都差不多吧
      下面列出我目前知道的兩個
      #AXISLABEL  X軸項目的標籤值
      #VALY           Y軸項目的標籤值
      當然如果是K線圖那種Y軸有多值的,應該可以用#VALY2.. 之類的取出吧,目前我還沒試過!

      設定滑鼠游標指到DataPoint時要出現甚麼說明,這個項目真的很強,在官方Example裡面有看到不只能像我這樣填寫文字,還可以放 html ,html就很強大了,因為基本上Chart控制項產生的結果就是一張圖片,所以可以透過img tag來連結另外一張單純只放chart的aspx檔然後依照我們傳送過去的參數來動態產生另一張小圖表,如果有興趣的話大家可以去參考官方Example "WebSamples\Interactivity\DrillDown\" 下面的程式
      設定顯示X軸的值當做Tip
      series1.ToolTip = "產品 : #AXISLABEL";

    • 繪製 Chart2
      請放在Chart1 的 Click事件中執行
      try
      {
          #region Step1. 設定 Chart Title
          Title ChartTitle = new Title();
          System.Drawing.Font font = new System.Drawing.Font("標楷體", 20);
          ChartTitle.Font = font;
          ChartTitle.ForeColor = System.Drawing.ColorTranslator.FromHtml("#6B8E23");
          ChartTitle.Text = e.PostBackValue + " 子圖表";
          #endregion
      
          #region Step2. 產生工作區塊(Area1)
          ChartArea cArea1 = new ChartArea("Area1");
          cArea1.AxisX.Title = "月份";
          cArea1.AxisY.Title = "數量";
          cArea1.AxisX.Interval = 1;
          cArea1.AxisY.Interval = 1;
          
          #region Step2.1 產生Area1的Series
      
          Series series1 = new Series("");
          series1.ChartArea = "Area1";
          series1.ChartType = SeriesChartType.Spline;
      
          //設定線圖粗度及樣式
          series1.BorderWidth = 3;
          series1.BorderDashStyle = ChartDashStyle.Solid;
      
          //填入資料
          using (DBObj oDB = new DBObj())
          {
              string sProductName = e.PostBackValue;
              var oNo = from oProduct in oDB.Product
                        where oProduct.Product1 == sProductName
                        select oProduct;
      
              int iNo = oNo.First().No;
      
              var DBData = from o in oDB.SaleDetail
                           where o.Year == "2008" && o.ProductNo == iNo
                           group o by new { o.Month } into D
                           select new { D.Key.Month, TT = D.Count() };
      
              foreach (var tmp in DBData)
              {
                  series1.Points.AddXY(tmp.Month, tmp.TT);
              }
          }
          #endregion
      
          #endregion
      
          #region Step3. 設定Legend
          Legend leg = new Legend("分類");
          leg.Docking = Docking.Right;
          Chart1.Legends.Add(leg);
          #endregion
      
          Chart2.Titles.Add(ChartTitle);
          Chart2.ChartAreas.Add(cArea1);
          Chart2.Series.Add(series1);
      
      }
      catch (Exception ex)
      {
          System.Web.UI.ScriptManager.RegisterStartupScript(Page, Page.GetType(), "Exception", " var s= alert('" + ex.Message.ToString().Replace("'", "").Replace("\"", "") + "')", true);
      }
  4. 展示結果
    最後結果就如同下方圖片,點選查詢將餅圖查出後點選餅圖然開啟各區塊的線圖來提供細部的說明
    Chart_2_3

 

 

程式碼下載 : Chart_Test3.zip

 

 

 

===========================這是簽名檔分隔線==============================
我沒有甚麼技術能力
不過卻希望在這邊跟大家分享自己遭遇的一些問題
希望大家有更好的方法可以跟我說!!
======================================================================