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:
    
        


    这边稍微说明一下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 "WebSamplesInteractivityDrillDown" 下面的程序
      设定显示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

===========================这是签名档分隔线==============================
我没有什么技术能力
不过却希望在这边跟大家分享自己遭遇的一些问题
希望大家有更好的方法可以跟我说!!
======================================================================