椰子林软件教育基地

做一个诚实的人,你也一样。

用户操作
[即时聊天] [发私信] [加为好友]
椰子林ID:lizanhong
118838次访问,排名721好友0人,关注者1
lizanhong的文章
原创 40 篇
翻译 1 篇
转载 10 篇
评论 288 篇
椰子林的公告

    欢迎访问椰子林的Blog,本网站文章保证原创


联系方式:
网名:椰子林
QQ:2878685**
Email:lifenote(AT)21cn.com



最近评论
niuchn:请教一下,生成的WSDL文件在那能找到。如果需要修改WSDL文件。
jefferykk:好文章
ZqqL:感谢 楼主! 只是示例中
[ToolboxBitmap(typeof(NumberEditor),"PowerAsp.NET.Controls.NumberEditor.bmp")]
非常不懂,请楼主以后能在其他示例中详释
grfgfdsgd:抄人家的,无聊
dsp_1128:非常好,谢谢!
文章分类
收藏
相册
BBS
截图
我的生活照
友情链接
dotnetBlog
DotNet新网
Loveyuki 's BLOG
MSDN中文
中国DotNet俱乐部
椰子林DotNet的天空
海边看星(IT大杂烩)
存档
软件项目交易
订阅我的博客
XML聚合  FeedSky
订阅到鲜果
订阅到Google
订阅到抓虾
订阅到BlogLines
订阅到Yahoo
订阅到GouGou
订阅到飞鸽
订阅到Rojo
订阅到newsgator
订阅到netvibes

原创 Asp.net组件设计浅论收藏

新一篇: ASP.NET组件编程step by step | 旧一篇: (C#)利用反射动态调用类成员

Asp.net组件设计浅论

 

一、什么是组件?

查看MSDN,微软是这样给组件定义的:在 .NET Framework 中,组件是指实现 System.ComponentModel.IComponent 接口的一个类,或从实现 IComponent 的类中直接或间接派生的类。这是从纯语言(技术)角度下的定义,通俗的讲,组件是“可独立运作的软件单元”,这里强调独立运作,也就代表着组件必须拥有低耦合性、高重用性等特点。微软将软件划分为两部分:其一是Component,意指具备特定功能、可独立运作、不具备UI接口的单元;其二是Control,也就是我们常说的控件,意指具备特定功能、可独立运作的UI接口单元。

 

二、学习Asp.net组件需要掌握的知识

任意掌握一门.net语言,建议使用C#C#是一门全新的语言,但又借鉴了C++JAVA的语法,同时引入了一些新概念,在程序员中口啤不错。

理解IIS的运行机制和asp.net的运行模式。

熟练掌握javascript,该脚本语言强大的功能在处理客户端动作时表现非常出色,基本上所有的自定义组件都离不开javascript,同时,CSSDHTML也是要心知肚明的。没办法,他们很少会单独出现,总是喜欢集体演出。

 

三、组件设计的难度

这个问题不用问,也许您猜出了几分,一个字:难。

您也许会有所察觉,在编写asp.net应用程序时,很少会对viewstate作深入的研究,原因很简单,因为ViewState本身设计的用户对象本来就不是应用程序员,而是组件设计员。如果不是因为客户端需要,您也不会在asp.net中编写大量的javascript脚本,而在组件设计中,很难逃脱干系。不止这些,是否设计成服务器组件?我们的组件是继承Control、还是继承WebControl或是继承Component?在组件中,需要自定义Attribute吗?需要实现数据绑定吗?如何绘制组件的外观?如何和IIS通讯?需要post-back吗?很多很多的问题,都需要组件设计者——辛苦的您去一一考虑。

所以,如果您不屑一顾地说:不就是设计一个组件吗?这有何难!那么,我会嘿嘿一笑,因为我知道,您一定在开玩笑。

但是,千万别怕,“程序员需要探索精神哦!”

 

四、基类的选择

如果我们设计的是一个WEB可视控件,并且构成WEB页的一部分,那么可以继承Control类或者WebControl类。如果是一个非可视控件,可以继承Component,继承此类的控件设计时不会出现在页面上,而是出现在Component Tray中。还记得OpenFileDialog控件吗?这个文件打开对话框控件就是出现在Component Tray控件中的。

如果我们只是在已有的控件基础上增强功能,那么就继承该已有的控件吧。

 

五、实践出真知

假设我们要设计一个组件,该组件只允许用户输入数字,该验证工作自然应该放到客户端,客户端的验证脚本可以这样写:

 

<HTML>

<HEAD>

<META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0">

<TITLE></TITLE>

<script language="javascript">

function Virty(ctrl)

{

    if (event.keyCode == 13)

        return true

    if (event.keyCode < 48 || event.keyCode > 57)

        return false;

    else

        return true;

}

</script>

</HEAD>

<BODY>

 <form method="POST" >

      <p>

        <input type="text" name="T1" size="20" OnKeyPress="javascript:return Virty(this);">

      </p>

 </form>

</BODY>

</HTML>

 

       当然,这些验证代码不能由用户去写,应该由组件设计者去写,也就是说,当用户把该组件从工具箱中拖到页面上后,运行时应该自动生成验证代码。向WEB页绘制代码,我们重OnPreRender()方法就可以了。

       在重OnPreRender()方法之前,先写定义几个常量:

private const string SCP_NUMBER_ONLY_SCRIPT_ID="{29FD7A41-49FD-4fc4-AFA9-6A0B875A1A51}";

              private const string SCP_NUMBER_ONLY_HOOK="return Virty(this);";

              private const string SCP_NUMBER_ONLY_SCRIPT=

                     "<script language=\"JavaScript1.2\">\nfunction Virty (ctrl)\n{{\n"+

                              "if (event.keyCode == 13)\n return true;\n if (event.keyCode < 48 || event.keyCode > 57)\n return false;\n else\n return true;\n}}"+

                              "</script>";

       下面的方法用于验证代码的生成:

private void RenderJavaScript()

{

       if(!Page.IsClientScriptBlockRegistered(SCP_NUMBER_ONLY_SCRIPT_ID))       Page.RegisterClientScriptBlock(SCP_NUMBER_ONLY_SCRIPT_ID,string.Format(SCP_NUMBER_ONLY_SCRIPT,base.ID));

}

为什么会有Page.IsClientScriptBlockRegistered(SCP_NUMBER_ONLY_SCRIPT_ID)呢?我们想象一下,如果在WEB页中有十个该控件,那是不是就要输出十个这样的脚本?显然,这是画蛇添足了,所以,我们要用IsClientScriptBlockRegistered()判断该脚本是否在客户端输出,如果脚本在客户端已注册,则不再输出了。

接下来就是重OnPreRender()方法了,该方法负责向客户端绘制脚本。

protected override void OnPreRender(EventArgs e)

{

       base.OnPreRender (e);

       RenderJavaScript();                

}

大家应该注意到,该脚本需要事件触发才会执行,当用户从浏览器输入数据时,如果是非数字,则忽略该动作,否则才接受输入。这就需要OnKeyPress="javascript:return Virty(this);"这段代码了。那么,这段代码怎么向客户端输出呢?重写AddAttributesToRender()方法吧,该方法负责绘制组件的属性。于是,我们写了下面一段代码:

protected override void AddAttributesToRender(HtmlTextWriter writer)

{

       base.AddAttributesToRender(writer);              

       writer.AddAttribute("OnKeyPress",SCP_NUMBER_ONLY_HOOK);                 

}

       最后的源码如下:

/////////////////////////////////////////////////////////////////////////////

/// 注意,本代码版权所有者为黄忠成先生。

/// 在此表示感谢他写的书《ASP.NET组件设计》

////////////////////////////////////////////////////////////////////////////

using System;

using System.Text;

using System.Drawing;

using System.Web;

using System.Web.UI;

using System.Web.UI.WebControls;

namespace PowerAsp.NET.Controls

{

    [ToolboxBitmap(typeof(NumberEditor),"PowerAsp.NET.Controls.NumberEditor.bmp")]

    public class NumberEditor:BaseEditor

    {

        private const string SCP_NUMBER_ONLY_SCRIPT_ID="{29FD7A41-49FD-4fc4-AFA9-6A0B875A1A51}";

        private const string SCP_NUMBER_ONLY_HOOK="return NumberEditor_KeyPress_Handle(this);";

        private const string SCP_NUMBER_ONLY_SCRIPT=

            "<script language=\"JavaScript1.2\">\nfunction NumberEditor_KeyPress_Handle(ctrl)\n{{\n"+

            "if (event.keyCode == 13)\n return true;\n if (event.keyCode < 48 || event.keyCode > 57)\n return false;\n else\n return true;\n}}"+

            "</script>";                                              

        //rending number-limit javaScript.

        private void RenderJavaScript()

        {

            if(!Page.IsClientScriptBlockRegistered(SCP_NUMBER_ONLY_SCRIPT_ID))    Page.RegisterClientScriptBlock(SCP_NUMBER_ONLY_SCRIPT_ID,string.Format(SCP_NUMBER_ONLY_SCRIPT,base.ID));

        }

        protected override void AddAttributesToRender(HtmlTextWriter writer)

        {

            base.AddAttributesToRender(writer);           

            writer.AddAttribute("OnKeyPress",SCP_NUMBER_ONLY_HOOK);        

        }

        protected override void OnPreRender(EventArgs e)

        {

            base.OnPreRender (e);

            RenderJavaScript();         

        }      

        public NumberEditor():base()

        {      

        }

    }

}

 

发表于 @ 2004年07月15日 21:16:00|评论(loading...)|编辑

新一篇: ASP.NET组件编程step by step | 旧一篇: (C#)利用反射动态调用类成员

评论

#萧十一郎 发表于2004-07-15 21:51:00  IP: 222.64.99.*
最好给出如何调用此组件的例子。
#lizanhong 发表于2004-07-15 22:01:00  IP: 219.137.87.*
使用方法:
1、将该文件编译成dll程序集
2、新建一个WEB应用程序,在工具箱中点击右键,选择添加组件,找到第一步生成的DLL程序集,确定即可。
3、将该组件直接拖到WEB页面中。
#达到 发表于2004-07-20 13:23:00  IP: 61.144.60.*
都是废话
#jackie615 发表于2004-07-20 14:47:00  IP: 218.79.105.*
入门学习


需要专门找点书看看
#steeven 发表于2004-07-20 12:39:00  IP: 218.79.112.*
老兄,太少了。比如生成图片的控件,只是生成一个<img>tag, 那src该怎么指向,怎么响应呢?请指点

vs2005好像把这些东西都统一了,期待中。
#cgmx 发表于2004-07-20 19:21:00  IP: 61.144.60.*
大家都应该共享一下,真的可以把好的东西都编成组件.
#xtchl 发表于2004-07-20 19:24:00  IP: 218.75.231.*
关注中.
#junbo 发表于2004-07-21 23:18:00  IP: 210.83.247.*
请问:SCP_NUMBER_ONLY_SCRIPT_ID="{29FD7A41-49FD-4fc4-AFA9-6A0B875A1A51}";这组编码是怎样产生的?有什么用


#分古佛 发表于2004-07-21 23:40:00  IP: 219.139.193.*
guid 函数产生,
#boywdj@163.com 发表于2004-07-21 10:54:00  IP: 218.94.61.*
问一些关于代码的问题:
(1)代码是不是不全。因为public class NumberEditor:BaseEditor中的BaseEditor没有交代。
(2)Page.RegisterClientScriptBlock(SCP_NUMBER_ONLY_SCRIPT_ID,string.Format(SCP_NUMBER_ONLY_SCRIPT,base.ID));
中的base.ID表示什么,string.Format(SCP_NUMBER_ONLY_SCRIPT,base.ID)为什么不写成SCP_NUMBER_ONLY_SCRIPT?
谢谢,
#Davied2004 发表于2004-07-21 11:08:00  IP: 218.61.20.*
谢谢了啊,我正要这方面的知识
#lizanhong 发表于2004-07-21 11:14:00  IP: 219.136.41.*
boywdj@163.com :
如果要调试成功,请去掉:[ToolboxBitmap(typeof(NumberEditor),"PowerAsp.NET.Controls.NumberEditor.bmp")]

把BaseEditor改成TextBox

string.Format(SCP_NUMBER_ONLY_SCRIPT,base.ID),该语句对脚本进行格式化输出的任用。base.ID将代替SCP_NUMBER_ONLY_SCRIPT字符串中的占位符
#azmore 发表于2004-07-22 08:46:00  IP: 218.22.44.*
了解,感谢作者
#boywdj@163.com 发表于2004-07-21 14:21:00  IP: 218.94.61.*
不好意思,我还是不太明白,SCP_NUMBER_ONLY_SCRIPT中那个是占位符?base.ID在本控件中是什么字符串?
#飞叶 发表于2004-07-21 20:20:00  IP: 218.109.177.*
我估计作者现在在吐血
#莫过于 发表于2004-07-21 20:45:00  IP: 202.84.17.*
一个字:烂!!!!!!
#Rover 发表于2004-07-23 09:06:00  IP: 61.52.20.*
组件是一个功能,控件是组件的一种
#hbzxf 发表于2004-07-22 17:20:00  IP: 221.192.52.*
初学者很适合的,最好就是code排版有条理一些
#JASON.KING 发表于2004-07-23 12:02:00  IP: 218.1.114.*
一个字你说的是什么啊!我一个字也看不明白
#leafsoft 发表于2004-07-23 16:26:00  IP: 61.233.225.*
值得学习!
#newpant 发表于2004-07-23 14:15:00  IP: 61.149.65.*
建议看看M$出过的一本红皮书,是关于ASP.NET组件设计的,还不错
#QuKevin 发表于2004-07-24 11:32:00  IP: 61.180.26.*
不錯!
#Jacky 发表于2004-07-24 22:25:00  IP: 61.186.83.*
大家去看看那本书吧....
#波波 发表于2004-07-24 13:51:00  IP: 219.140.224.*
楼主辛辛苦苦讲了这么多,不支持还废话的都是些鸟人,不用理他们,楼主我支持你!
#blue 发表于2004-08-02 20:15:00  IP: 218.80.166.*
欢迎访问椰子林的Blog,本网站文章保证原创
//原创个JB
#.. 发表于2004-08-02 14:39:00  IP: 202.197.75.*
..
#.. 发表于2004-08-02 14:39:00  IP: 202.197.75.*
<script>alert('thanks');</script>
#月色疯狂 发表于2004-08-03 14:04:00  IP: 218.94.3.*
其实开发组件并没有作者说的那么难吧。不要吓唬大家来增加书的销量。.net framework中有示例和快速入门教程,看完之后就已经足够完成开发组件的任务了。组件就是个类,难什么?
#111111111 发表于2004-08-06 12:49:00  IP: 218.7.215.*
呵呵,这个好像真的不是原创,我在好几本书上都看了!
#lizanhong 发表于2004-08-09 11:40:00  IP: 218.19.33.*
这文章是我写的,文中的例子是黄忠成先生的,我已在文中做了说明.如果您在别的地方看到过此文,一定是转载我的.
谢谢!
#TOM 发表于2004-08-24 11:18:00  IP: 211.157.112.*
呵呵,大家都是神仙,何苦呢?楼住辛苦!
#嘿嘿 发表于2004-08-24 21:08:00  IP: 218.61.64.*
作者是个写书的好料,文笔不错,难得可贵的是有极大的耐心,不妨向技术写作方面发展.
#新手 发表于2004-08-26 16:37:00  IP: 61.134.6.*
当引用以后,从工具栏里面拖动此组件到WebForm里面的时候,自动生成一个文本框.我怎么在上面的代码里面看不出是怎么生成文本框的呢?多谢
#lizanhong 发表于2004-08-26 17:03:00  IP: 218.19.210.*
这个例子继承了TextBox控件。
#ZqqL 发表于2007-11-01 11:12:03  IP: 219.133.83.*
感谢 楼主! 只是示例中
[ToolboxBitmap(typeof(NumberEditor),"PowerAsp.NET.Controls.NumberEditor.bmp")]
非常不懂,请楼主以后能在其他示例中详释
发表评论  


登录
Csdn Blog version 3.1a
Copyright © 椰子林