B.2 项目设计
DateChooser控件涉及方方面面,要完成它,第一件事情就是要想清楚,什么功能该在什么地方用什么方式来实现?
B.2.1 项目分解
在前面,我们提到DateChooser控件拥有非常丰富的交互功能。那么这些功能怎么实现呢?
首先,确定这些交互在哪里执行?我们的控件是为了克服Calendar控件带给用户断断续续的糟糕体验,Calendar之所以不断打断用户操作,是因为每一步操作它都需要往返服务端,把用户的交互提交到服务端处理。因此,DateChooser与用户的交互过程应往前推,在客户端完成,也就是说,DateChooser大部分的交互功能应该用Javascript来完成。显然,脚本是DateChooser控件的关键。
服务端逻辑,也就是控件代码,则主要集中在组织脚本文件,呈现控件的初始化代码。另外,设计时效果的实现,也是控件逻辑的一大重点。
B.2.2 客户端设计
整个客户端由脚本、样式文件和一些图片组成,如图B-15所示。


图B-15 客户端文件
其中Javascript是组织者、执行者。在这个项目中,我们使用了ASP.NET AJAX脚本类库中的Ajax.js文件,这个文件中的脚本模拟实现了面向对象的脚本框架,此处并没有太多利用其面向对象的功能,在后面实战中,我们会应用这些功能。DateChooser主要利用了Ajax.js文件中对Javascript基础类型的扩展功能,比如对Date类型的扩展,以及对Dom对象的扩展。
整个客户端脚本是基于JQuery来编写的。DateChooser最终呈现的DOM结构比较复杂,使用JQuery使得对DOM结构的操作轻松了许多,如图B-16所示。

图B-16 DateChooser的DOM结构
在DateChooser的内部结构中,我们使用了很多class,而不是id或name属性,这样做使得用户可以方便而细致地通过编辑CSS样式表定制控件的最终视觉效果,同时,借助于JQuery,class属性可以帮助我们轻松地查找并操作元素。Class属性也不像ID那样有必须全局唯一的限制,所以我们也避免了生成dateChooser1_input或dateChooser1$input这样的冗余而不一致的HTML代码。
注:Class属性虽然通常用于对于样式表中的类,但从本质上讲,它算是一个结构性的属性,所以Transceding CSS等书籍都推荐对类名取值时多使用表意的词语,比如Header,而不是表象的词语,比如Red。
B.2.4 服务端设计
DateChooser控件核心的类只有一个,那就是DateChooser类,不过为了提供丰富的设计时功能,我们围绕它实现了很多类,其中包括一个Designer,一个ActionList,一个Editor,五个TypeConverter,如图B-17所示。

图B-17 DateChooser类图







