一、 引言
在许多B/S结构的信息管理软件中,利用在线统计图帮助用户观察、分析各种各样的数据,要比纯粹依靠统计表格更直观,更形象。然而,与窗体类程序相比,在WEB中实现统计图功能存在着一些差别,如果利用现有的ActiveX统计图控件,将其直接嵌入网页前端脚本内,那么必须要求客户端下载安装相应的控件资源。而且容易导致系统安装维护、分布式数据访问等性能上的问题。区别于这种“胖客户”的方法,另外一种做法是,在服务器端通过数据运算,动态生成统计图像后,再向前端发布。显然,后一种方法是一种较好的模式,它对客户端的软件配置要求很低,只要前端安装浏览器即可。
目前,已经有一些ASP.NET技术文章中探讨了web图表问题,一般都是先运用GDI+绘制统计图表,再利用Response对象将图像流发送到客户端浏览器。但笔者认为,对于大多数普通编程人员来说,这种开发方式对开发者的图形编程技术功底要求很高,而且费时费力。因而,在短时间内很难开发出表现力强,具有一定的通用性的专业WEB控件。那么有没有一些近在咫尺的技术可以让我们很快解决这一问题呢?笔者认为OWC组件是一个很好的选择。OWC (Office Web Componsents)是一组随微软OFFICE一起发布的COM控件的集合,其中Chart(图表)组件类似于Excel中的图表制作功能,能支持几十种图表类型,其非凡之处在于它们不仅可以在诸如WEB页面、VB表单等控件容器中使用,而且也可以在内存中作为不可见对象使用。下文笔者将综合几种技术阐述如何利用OWC组件开发WEB统计图表控件。
二、 设计原理
实现的基本思路是将OWC Chart组件运行于服务器上,运用其丰富的编程接口导入数据源,设置图表格式和类型后,用ExportPicture方法导出临时GIF文件,再结合ASP.NET技术,将此GIF图像返回至客户端浏览器中规定位置,最后,删除临时GIF文件,回收资源。
笔者在开发过程中发现,真正的难点并不在于怎么使用OWC的接口,而在于怎样将图形发送至客户端浏览器?怎样将以上思路转换成自定义Web Control?又如何删除过期的临时GIF文件?下面我们将一步一步的构建自定义WebChart控件。
三、 WebChart控件的开发步骤
1. 建立工程WebChart
运行Visual Studio.net,选择文件->新建->项目->Visual C#项目->Web控件库,如图1,建立工程名为WebChart,建立类文件WebChart.cs, 选择菜单项目->添加引用弹出对话框如图2。
![](https://p-blog.csdn.net/images/p_blog_csdn_net/xqzl/1.png)
按“浏览”按钮找到OWC10.DLL后,选择“确定”,完成WebChart对OWC资源的引用。值得注意的是,OWC组件的各个版本有所不同,为了帮助正确安装和使用,现将其罗列于下表:
组件主要文件 | 对应的Office版本 | 机器上的一般安装位置 |
MSOWC.DLL | OFFICE 2000 | /Program Files/Microsoft Office/Office |
OWC10.DLL | OFFICE XP | /Program Files/Common Files/Microsoft Shared/ Web Components/10 |
OWC11.DLL | OFFICE 2003 | /Program Files/Common Files/Microsoft Shared/ Web Components/11 |
2. 继承WebControl基类,对ChartSpace类进行封装
双击WebChart.cs查看代码,进入编辑状态,建立命名空间WebChartCtl,编辑如下代码,并参看其中注释内容:
using
System;
using
System.Web.UI;
using
System.Web.UI.WebControls;
using
System.ComponentModel;
using
System.Drawing;
using
System.Drawing.Imaging;
using
System.Web;
using
System.Xml ;
using
System.IO;
using
OWC
=
Microsoft.Office.Interop.Owc11;
using
System.Runtime.InteropServices;
using
System.Data;
using
System.Data.OleDb;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
namespace
WebChartCtl
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
[DefaultProperty(""), ToolboxData("<{0}:WebChart runat=server></{0}:WebChart>")]
public class WebChart : System.Web.UI.WebControls.WebControl
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
private ChartSpaceClass m_ChartSpace;
//构造函数,调用基类构造函数来指定服务器控件应该在浏览器输出一个<IMG></IMG>标记
public WebChart():base("IMG")
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
try...{
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
m_ChartSpace=new ChartSpaceClass();
m_ChartSpace.DisplayFieldButtons=false;
m_ChartSpace.DisplayFieldList=false;
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
}catch...{}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
//显露OWC组件的图形空间对象
public ChartSpaceClass ChartSpace
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
get...{return m_ChartSpace;}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
//导出临时GIF图形文件
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
private string ExportGifFile()
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
string filename=GetTemp();//产生唯一的文件名
//导出GIF文件
object o;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
if (m_ChartSpace.DataSource==null)// || m_ChartSpace.ConnectionString==null || m_ChartSpace.ConnectionString=="")
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
filename="__NULL";
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
else
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
o=this.m_ChartSpace.GetPicture("gif",(int)this.Width.Value,(int)this.Height.Value);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
this.Page.Cache[filename]=o;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
this.m_ChartSpace.Clear();//释放图表对象使用的资源
if (m_ChartSpace!=null)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
if (m_ChartSpace.DataSource!=null)
Marshal.ReleaseComObject(m_ChartSpace.DataSource);
Marshal.ReleaseComObject(m_ChartSpace);
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
this.m_ChartSpace=null;
GC.Collect();
GC.WaitForPendingFinalizers();
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
return filename;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
//产生唯一的文件名
private string GetTemp()
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
System.DateTime T=System.DateTime.Now;
return "T"+T.Date.ToShortDateString()+T.Hour.ToString()+T.Minute.ToString()+T.Second.ToString()+T.Millisecond.ToString()+".gif";T"+T.Date.ToShortDateString()+T.Hour.ToString()+T.Minute.ToString()+T.Second.ToString()+T.Millisecond.ToString()+".gif";
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
}//end of namespace
在以上的命名空间WebChartCtl中,首先利用基类WebControl的缺省构造函数确定该控件在前端将显示为<IMG>元素,接着封装ChartSpace对象属性是为了将OWC Chart组件的编程接口委派给WebChart组件,从而保证可以再利用OWC所有编程特性,ExportGifFile是一私有方法,用于将ChartSpace中图表输出成临时的图形文件,为后面向浏览器传递图形做好准备。接下来,覆盖基类AddAttributesToRender方法,为前端<img>控件设置图形源属性Src。
在同一命名空间WebChartCtl中插入以下代码:
protected
override
void
AddAttributesToRender(HtmlTextWriter writer)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
base.AddAttributesToRender (writer);
string src,filename;
try
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
filename=this.ExportGifFile();//产生临时图形文件
//设置<img>图形源属性Src,利用参数filename传递临时图形文件名
src="handler.aspx?filename=" +this.Page.Server.UrlEncode(filename);
writer.AddAttribute(HtmlTextWriterAttribute.Src,src );
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
catch...{}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
以上代码中handler.aspx是临时图形文件的逻辑载体,需要根据URL参数表中filename的取值,负责处理请求,产生图形流,并发送至前端。
3. 利用IHttpHandler 接口捕获Http请求
以上过程通过设置src属性向WEB服务器请求处理,那么,是否必须要设计一个handler.aspx文件,并在其中写入代码来处理客户端提交的Http请求呢?其实,并不需要这样做,否则我们的封装行为就毫无意义了。ASP.NET提供了IHttpHandler接口,可以自定义 HTTP 处理程序来处理特定的、预定义类型的 HTTP 请求,IHttpHandler位于命名空间System.web中。
使用IhttpHandler必须实现ProcessRequest方法、IsReusable属性,在namespace WebChartCtl中建立公有类RequestHandler用于捕获Http请求,插入代码如下:
public
class
RequestHandler:IHttpHandler
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
//处理请求
public void ProcessRequest(HttpContext context)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
string filename=context.Request.QueryString["filename"];
context.Response.ContentType="image/gif";
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
if (filename=="__NULL")
DrawBmp(context.Response.OutputStream);
else
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
object o=context.Cache[filename];
byte[] s=(byte[])o;
context.Response.BinaryWrite(s);
context.Cache.Remove(filename);
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
private void DrawBmp(System.IO.Stream st)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
Bitmap bitmap = new Bitmap(1,1);
Graphics graphics = Graphics.FromImage(bitmap);
graphics.Clear(Color.White);
// graphics.DrawString("版权所有 (C) 2001-2020",new Font("Courier New",11,FontStyle.Underline),Brushes.Black,new PointF(5,5));
bitmap.Save(st,ImageFormat.Gif);
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
//获取一个值,该值指示其他请求是否可以使用 IHttpHandler 实例
public bool IsReusable
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
get...{return true;}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
在ProcessRequest中,利用WriteFile将ExportPicture方法生成的临时GIF文件直接写入 HTTP 内容输出流。
4. 对Web.config文件的设置
编译以上程序生成WebChart.dll,为了能让IhttpHandler起作用,还必须在测试工程的web.config文件中加入以下配置信息:
<configuration>
<system.web>
<httpHandlers>
<add verb="*" path="handler.aspx" type="WebChartCtl.RequestHandler,WebChart" />
</httpHandlers>
</configuration>
其中path属性值为请求文件名,type属性值由组件命名空间WebChartCtl、IhttpHandler接口实现类名RequestHandler、组件文件名WebChart组成的字符串:"WebChartCtl.RequestHandler,WebChart"。显然,这种配置行为给组件WebChart的使用带来了一些不便,考虑到web.config是XML文档,我们完全可以用System.xml来自动完成对web.config的配置,在类WebChart中插入代码如下:
//
在WEB.CONFIG中配置HttpHandler
private
void
RegesterHttpHandler()
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
string spath="handler.aspx";
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
string stype="WebChartCtl.RequestHandler,WebChart";
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
string filename=this.Page.Request.PhysicalApplicationPath + @"web.config";
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
XmlNode root, e,HttphandlerNode;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
XmlDocument xmldoc= new XmlDocument();
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
xmldoc.Load(filename);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
root=FindElement(xmldoc.DocumentElement,"system.web");
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
if (root==null) return;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
e=FindElement(root,"httpHandlers");
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
if (e==null)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
HttphandlerNode=xmldoc.CreateElement("httpHandlers");
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
this.CreateAddElem(xmldoc,(XmlElement)HttphandlerNode,spath,stype);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
root.InsertBefore(HttphandlerNode,root.FirstChild);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
else
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
SeekAddElemAndCreateIt(xmldoc,e,spath,stype);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
xmldoc.Save(filename);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
//
子过程,寻找指定的节点
private
XmlNode FindElement(XmlNode elem,
string
elemName)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
XmlNode findit=null;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
foreach(XmlNode e in elem.ChildNodes)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
if(e.Name.ToLower()==elemName.ToLower())
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
findit=e;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
return findit;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
//
查看是否包含<add>节,如果配置信息不正确修正它
private
void
SeekAddElemAndCreateIt(XmlDocument xmldoc, XmlNode HttphandlerNode,
string
spath,
string
stype)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
XmlNode findit=null;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
bool b=false;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
foreach(XmlNode e in HttphandlerNode.ChildNodes)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
if(e.Name.ToLower()=="add")
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
b=(e.Attributes["verb"].InnerXml=="*")&&
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
(e.Attributes["path"].InnerXml.ToLower()==spath.ToLower())&&
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
(e.Attributes["type"].InnerXml.ToLower()==stype.ToLower());
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
if (b) ...{findit=e;break;}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
if (!b) CreateAddElem(xmldoc,(XmlElement)HttphandlerNode,spath,stype);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
//
创建<add>节的配置信息
private
void
CreateAddElem(XmlDocument xmldoc,XmlElement HttphandlerNode,
string
spath,
string
stype)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
XmlElement subnode;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
subnode=xmldoc.CreateElement("add");
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
subnode.SetAttribute("verb","","*");
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
subnode.SetAttribute("path","",spath);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
subnode.SetAttribute("type","",stype);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
HttphandlerNode.InsertBefore(subnode,HttphandlerNode.FirstChild);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
//
在Web页初始化时,对web.config中填入正确的设置
protected
override
void
OnInit(EventArgs e)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
base.OnInit (e);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
this.RegesterHttpHandler();
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
四、 WebChart控件的应用实例
至此,已完成所有组件代码的编写,将工程WebChartCtl编译为WebChart.dll,即可测试应用。步骤如下![](https://p-blog.csdn.net/images/p_blog_csdn_net/xqzl/2.png)
1) 在磁盘上建立名为TestChart的文件夹,并利用IIS将其设为虚拟目录,如图3,在Visual Studio.net 开发环境中选择文件->新建->项目->Visual C#项目->ASP.NET Web应用程序,并和WebChartCtl一样,引用OWC10.DLL(如图2),选右键菜单,将测试表单WebForm1设为“起始页”,并确保Web.Config文件可读写。
2) 从工具箱选项夹“WEB窗体”中拖动Lable,向WebForm1中添加控件Lable1, Text属性设为“WebChart运行实例”;
3) 在工具箱上,右键选择“添加/移除项”,弹出对话框如图4,选择“浏览”找到“…./WebChartCtl/bin/Debug/WebChart.dll”,将控件WebChart显示于工具箱中,拖动WebChart图标,为WebForm1中添加控件WebChart1
4) 双击WebForm1,编辑以下代码:
using
OWC10;
private
void
Page_Load(
object
sender, System.EventArgs e)
{
//
创建图表空间实例
OWC10.ChartSpaceClass Chs
=
this
.WebChart1.ChartSpace;
//
设置数据库连接串以及SQL数据命令
Chs.ConnectionString
=
@"
Provider=SQLOLEDB;Data source=(local);Initial Catalog=northwind;User Id=sa;Password=
"
;
Chs.CommandText
=
@"
SELECT YEAR(ShippedDate) AS YEAR, MONTH(ShippedDate) as month,SUM(Subtotal) AS Total FROM [Summary of Sales by Year] GROUP BY YEAR(ShippedDate), MONTH(ShippedDate)
"
;
//
设置图表的系列,分类轴,数据轴
Chs.SetData(ChartDimensionsEnum.chDimSeriesNames,
0
,
"
YEAR
"
);
Chs.SetData(ChartDimensionsEnum.chDimCategories,
0
,
"
MONTH
"
);
Chs.SetData(ChartDimensionsEnum.chDimValues,
0
,
"
Total
"
);
//
设置标题
Chs.HasChartSpaceLegend
=
true
;
Chs.HasChartSpaceTitle
=
true
;
Chs.ChartSpaceTitle.Caption
=
"
Summary of Sales by Year
"
;
ChChart Cht
=
Chs.Charts[
0
];
//
设置图表类型,缺省为直方图,显现以下一行代码即为立体饼图
//
Cht.Type=ChartChartTypeEnum.chChartTypePie3D;
//
当图表类型为ChartChartTypeEnum.chChartTypePie3D时,
//
以下代码必须去除,否则代码无法执行
ChAxis X,Y;
Y
=
Cht.Axes[ChartAxisPositionEnum.chAxisPositionLeft];
Y.HasTitle
=
true
;
Y.Title.Caption
=
"
Total
"
;
Y.NumberFormat
=
"
Currency
"
;
X
=
Cht.Axes[ChartAxisPositionEnum.chAxisPositionCategory];
X.HasTitle
=
true
;
X.Title.Caption
=
"
Year
"
;
}
运行工程,结果如图5,如果根据代码注释内容修改代码,运行结果如图6。以上代码运行环境为Windows 2000 Professional,IIS5.0,Visual Studio.NET 2003, Office XP, SQL Server 2000。
![](https://p-blog.csdn.net/images/p_blog_csdn_net/xqzl/3.png)
五、 总结
以上内容综合了自定义
WebControl
技术、
XML
技术、
IHttpHandler
接口使用方法,对
OWC10
进行了重新封装,为实现
WEB
统计图表功能提供了一个非常实用的解决方案。笔者在
WebChart
中只对
OWC10
中的接口
ChartSpace
进行了封装,目的在于不丢失
OWC10
编程时的灵活性
,
有兴趣的读者可以进一步研究
OWC
的帮助文档,设计出贴近个性需求的接口。