打印

[asp.net教程] asp.net组件设计浅论

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,同时,css和dhtml也是要心知肚明的。没办法,他们很少会单独出现,总是喜欢集体演出。
   
   
   
  三、组件设计的难度
   
  这个问题不用问,也许您猜出了几分,一个字:难。
   
  您也许会有所察觉,在编写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()
   
  {
   
  }
   
  }

TOP

返回顶部
AYBlue

Processed in 0.059243 second(s), 7 queries.

当前时区 GMT+8, 现在时间是 2009-1-10 10:52 京ICP备06054220号

清除 Cookies - 联系我们 - 163K.com - Archiver - WAP