多数在表示层应用的服务器控件主要由两个部分组成:服务器端功能和客户端功能。服务器端功能永远是服务器控件的核心,而随着技术的发展,客户端功能也逐渐 变得越来越重要。只有两个部分互相配合,才能创建出功能强大、界面丰富的服务器控件。本文将讨论在服务器控件中实现客户端功能的相关问题,具体内容包括客 户端功能概述、实现简单客户端功能、实现复杂客户端功能,以及部署客户端文件的实现方法等内容。
1. 客户端功能简介
在Web编程中,客户端功能传统上是由Web页开发人员负责,并且不被封装在服务器组件中。ASP.NET脱离了这一范畴并使服务器控件能够发出客户 端脚本,从而使服务器控件能够将客户端处理与服务器端处理结合起来。实现客户端功能对于提高服务器控件的交互性和可扩展性的意义重大。例如,常见的 TreeView、TabStrip、ToolBar控件等,这些优秀的服务器控件具有很强的交互性和丰富的用户界面,而这些特征的实现与客户端功能是密 不可分的。
实现客户端功能的技术主要是客户端脚本(JavaScript、VBScript等)和DHTML。因此,作为一名合格的开发人员必须具有熟练应用这 些技术的能力。除此之外,还要掌握将客户端功能与服务器控件密切结合的方法。这些内容包括:实现简单客户端功能、实现复杂客户端功能、部署客户端脚本文件 的方法。
2. 实现简单客户端功能
如果自定义服务器控件的客户端功能比较简单,例如,仅仅是弹出窗口或者改变背景颜色等,那么对于这种情况,通过不使用单独的客户端脚本文件封装,而是 直接在控件呈现中实现。其实现的关键是在控件的Attributes中添加适当的客户端处理程序。以下实例说明从 System.Web.UI.WebControls.Button类派生的控件MyClickButton,它为客户端单击事件提供事件处理程序。请看 下面的代码:
public class MyClickButton : Button{ //相关代码 ...... protected override void AddAttributesToRender(HtmlTextWriter writer) { base.AddAttributesToRender(writer); writer.AddAttribute("onclick", "window.confirm('谢谢您! ');"); } } |
如果读者已经阅读了前面有关控件呈现的文章,那么很容易理解以上代码。以上代码重写了AddAttributesToRender方法,它为 MyClickButton控件定义了一个名为onclick的Attribute,其值指示在客户端弹出一个包含自定义信息的确认窗口。如果读者所开发 的服务器控件的客户端功能都比较简单,那么可以尝试利用重写AddAttributesToRender的方法予以实现。
下面是为使用MyClickControl控件而创建的ASPX页面源代码。
<%@ Page Language = "C#" %> <%@ Register TagPrefix="Custom" Namespace="MyControls" Assembly = "MyControls" %> <html> <body> <form runat=server> 请点击下面的按钮 <Custom:MyClickButton Id = "demo" runat=server/> <br> </form> </body> </html> |
当用户点击MyClickControl控件时,立刻弹出一个包含提示信息的确认窗口。需要注意的是弹出确认窗口并不是由于页面回传,而是用户激发客户端处理程序的结果。当点击"确定"按钮之后,才会发生页面回传。
3. 实现复杂客户端功能
如果客户端功能比较复杂,这时一般将完成其功能的代码封装在客户端脚本文件中。为了将这些脚本文件与服务器控件紧密结合起来,.NET 2.0框架提供了将客户端脚本文件加入服务器控件所需的必要方法。这些方法基本都包含在ClientScriptManager类中。开发人员可以通过调 用Page类的ClientScript属性来获取ClientScriptManager类实例。该类用于管理脚本、注册脚本和向页添加脚本。
可能读者对于ClientScriptManager类有些陌生,它是ASP.NET 2.0的新增类。该类是专门用于替代已经停止使用的用于管理脚本的Page类的部分方法而创建的,例如,在ASP.NET 1.x中曾经出现的RegisterClientScriptBlock、RegisterStartupScript等等,这些方法都已经停止使用,而 改用ClientScriptManager类的相关方法来实现。
下面列举了来自ClientScriptManager类的,与实现复杂客户端功能有关的几个常用方法。
(1)RegisterClientScriptBlock方法
向页的顶部添加一个脚本块。以字符串形式创建脚本,然后将其传递给方法,方法再将脚本添加到页中。可以使用此方法将任何脚本插入到页中。请注意,脚本可能在所有元素完成之前呈现到页中;因此,您可能无法从脚本中引用页上的所有元素。
(2)RegisterClientScriptInclude方法
与 RegisterClientScriptBlock 方法类似,但此方法将添加引用外部 .js 文件的脚本块。包含文件在任何其他动态添加的脚本之前添加;因此,您可能无法引用页上的某些元素。
(3)RegisterStartupScript方法
向页中添加一个脚本块,该脚本块在页完成加载后引发页的 onload 事件之前执行。该脚本通常不创建为事件处理程序或函数;它通常只包含要执行一次的语句。
(4)RegisterOnSubmitStatement方法
添加响应页的 onsubmit 事件而执行的脚本。该脚本在提交页之前执行,允许您取消提交。
(5)IsStartupScriptRegistered方法
确定Page对象是否注册了启动脚本。
(6)IsClientScriptBlockRegistered方法
确定Page对象是否注册了客户端脚本。
除了以上几个方法之外,ClientScriptManager类还包括其他一些相关方法,有兴趣的读者可以阅读相关资料。通过在服务器控件中灵活使用以上方法,我们可完成为控件加入客户端行为,同时也带来了以下好处:
(1)有效的减少所显示页面的大小,因为很多有关客户端功能的代码都封装到了客户端脚本文件中,在控件中只需引用脚本文件的地址即可。
(2)由于同一控件共享脚本文件,因此通过浏览器的缓存机制,可以改善应用程序的性能。
(3)提高了控件的灵活性和可扩展性。通过修改脚本文件,控件开发者可以很容易的修改客户端功能而不用编译服务器控件。
另外,在对复杂客户端功能处理的过程中,有时还需要在客户端脚本中访问控件。控件开发者可以在脚本中访问呈现到客户端的对象,并且对其进行操作。下面来简单介绍一些有关内容。
Control基类有一个ClientID的属性,它作为所呈现的元素的ID属性呈现。ASP.NET动态为一个控件生成ClientID,并且确保 页上每一控件的ClientID是唯一的。因此,可通过在文档对象模型中使用控件的ID在客户端上访问该控件(即,由该控件呈现的元素)。控件还可以使用 ClientID为它可以呈现的任何附加元素(例如隐藏域)生成唯一名称。
将ClientID的值发出到内联脚本中(或者发出到脚本库的代码中)可能是较为棘手的,因为该ClientID必须插在字符串变量中的正确位置。以下实例使用转义符将ClientID插入构成内联脚本的字符串中。
string element = "document.getElementById(\"" + ClientID + "\")"; Page.RegisterArrayDeclaration("Page_Validators", element); |
另外,还可以使用String类的重载的Format方法撰写使用ClientID的客户端脚本。
4. 部署客户端文件的方法
默认安装的情况下,在wwwroot文件夹下存在一个子文件夹asp_client,其中保存了用于支持智能导航、验证控件等功能的客户端脚本文件。很显然这些文件非常重要。为了提高应用的规范性,建议开发人员在部署客户端文件过程中,采用以下方法。
· 将包含有客户端脚本的文件夹置于asp_client文件夹中,尤其是对于那些安装在全局配件缓存(GAC)中的控件更应该这样做。
· 包含脚本的文件夹推荐使用与控件相关的名称。
· 推荐在包含脚本的文件夹下不要直接放置脚本文件,而是再创建一个名称为控件版本号的文件夹,将脚本文件放置其中。
例如,开发人员创建了一个版本为1.0的服务器控件MyControl,其关联一个客户端脚本ClientScript.js,并且将该控件加入了 GAC中。这时推荐部署客户端脚本文件的路径为:c:\Inetput\wwwroot\asp_client\MyControl_Client \1.0\ClientScript.js。另外,在客户端文件库中存储的并不仅是脚本文件,也可以加入控件所需的样式表文件、图片等其他文件。
以上为部署客户端文件的推荐方法,那么这是不是说明所有的客户端脚本文件都需要遵循以上规则呢?当然不是。只要开发人员从实际出发,从提高程序的可维护性和方便性着眼,那么无论客户端脚本文件置于何处,都是可以的。
5. 小结
本文主要介绍了与实现服务器控件客户端功能相关的内容。这些内容对于开发出交互性强的服务器控件非常重要。掌握这些内容并不困难,真正困难的是如何开 发完成客户端功能的CSS文件、JS脚本、DHTML程序等。这些技术的掌握不是一朝一夕就可以完成的,它需要扎实的基础,刻苦的钻研。而所有这些技术和 精神品质都是一名合格的开发人员所必需掌握的精髓,缺一不可。