五、控件结构
上一章讲的是如何实现多语言的设计,本章来讲一下控件部分。
不管后端的代码多么完善,多么完美,最后都要以一定的形式展示出来,并且要使用灵活,这时就会用到控件。
在ASP的年代,去写这种控件基本上是一件很痛苦的事情,现在简单多了,在asp.net技术中,有两种写控件的方式,一种是WEB用户控件,这种方式可以采用可视化编程方式,但是使用非常不灵活,并且不能编译成DLL文件,不能拥有自己的参数,完全要靠页面get/post过来的参数,不适合复杂的场景。另一种方式是写用户自定义组件,这种方式没有可视化编程,完全要靠手写代码,但是它的优点很多,比如可以生成DLL,可以加载到左侧工具栏供调用,可以设置参数及属性等,在我的程序中,后端管理程序全是用的后者。
我用的大部分控件由http://www.infragistics.com/ 的控件继承得来。最主要的一个控件是继承自它的UltraWebGrid控件,这个控件比微软自带的Grid控件要好很多,拥有WinForm的效果,本系统对它进行继承的作用是加入对MetaData的支持,并取名作:DBGridPro。在这个类中,有一个函数名为:MakeStructure,是对GRID进行初始化,根据构造函数中指明的ContentType,去数据库中取出这个类型所对应的所有的Attribute(字段),然后填充到DBGridPro的表头中,在Attribute中,规定了字段用于显示的名字,还有显示宽度等,在这里都得到了一一的体现,如果字段规定为只读,那么在表格中也会做相应的只读处理,如果是隐藏,那么在GRID中也会设为不可见,这样,我的DBGridPro就把该ContentType做了一个原样的重现。
Grid控件除了展示数据外,还有个很重要的功能就是实现对数据的更新,在传统的HTML+ASP的操作中,对数据的更新一般很难有CS的效果,都是写几个文本框,加一个提交按钮来实现,现在有这个控件就方便多了,只要在GRID中双击一下,就实现对数据的编辑,当然这完全得益于我所继承的控件的原始功能,然后只要鼠标点中当前行以外的任何地方,都会实现对当行数据的修改,这个功能是我重载了UpdateRow这个事件,加入我的代码来实现的。这些代码完全封装起来了,在写程序调用此控件的时候,完全不需要理会,只要给它指定了一个ContentType即可。因为这部分代码量比较大,所以在此不再粘贴。
还一个比较有特色的控件,叫做“字典”控件,在OracleEBS中也叫做种子数据,比如性别分为男和女,学历包括小学、中学、大学等几种,把所有这些内容全部组织在两张表中,一个是ZR_DICT_CATEGORY,存储字典的名字,如“性别”、“学历”,第二张表是ZR_DICT,存储字典的明细,如“男”,“女”,“小学”等,在使用的时候,会给字典控件指定一个字典的名称,如 dict.DictName = “GENDER”,这样,在实际运行时候,就会在字典控件中列出“男”和“女”两项,很方便,如果在数据库中对字典的内容进行了扩充,在控件中就会自动得到体现,而且不需要写任何的SQL代码。
对于以上的情况,所需要的字典的内容全部来自于同一张表,在有些情况下,并不是很方便,比如需要选择“用户类型”,可能有专门的表存储它,因为在字典中存储的信息是有限的,这时就不能很好的利用字典控件了,为了解决这个问题,有一个专门的控件叫做“值集”控件,这也是从OracleEBS中学习得来。与字典控件相比,这个控件在寻找数据源的时候,会根据存储的一个SQL语句来寻找,如:select user_type_id,user_type from zr_user_type,并用用户类型ID及名称来填充相应的控件。
以上两个控件都使得在使用本系统的时候,可以做非常灵活的应用。
现在继续说上面的GRID控件,为了对它实现更多的扩展和灵活性,写了一个页面,叫做content_invoke.aspx,里面放置了一个GRID控件,页面接收参数来指明是哪个ContentType,然后在page_load方法中实现数据的抓取。
在WinForm的程序中,GRID控件都有很丰富的筛选功能,用起来也很方便,只要在相应的列上点选一下,就像Excel那样,可以直接选择需要哪些数据,但是在IE中,好像无法做成这个效果,所以针对记录的筛选,不同的系统也有不同的做法,一般的做法是做很多的文本框,用于不同的条件输入,或者搞一个下拉列表输入不同的条件,但是一般很难做到复杂条件的组合。我做的这个Filter控件,也是与Content绑定,他会把ContentType所有的属性读出来,作为筛选的条件,并且会检查它的字段类型,来决定用于输入值的地方该用什么控件来接收,如日期型或数值型等,对于一个字段,可以有两个条件,中间可以用And或者Or来做连接,这样“拼装”起来后,就会形成一个复杂的SQL条件,把它附加在查询语句的最后,就可以实现按条件来查询了。这个控件与DBGridPro一起,放在content_invoke.aspx页面中一起使用。
在“Meta-Data驱动”一章中,我们曾经提到了“子表”的概念,这个也是在content_invoke.aspx中得到了体现,程序把这个页面分成上下两部分,上面用于显示ContentType的主体内容,所有子表全放在下面部分显示,如果有多个子表,会放在不同的Tab中来显示,每个子表部分,其实也是放了一个DBGridPro来显示,最后拼装起来就出现了一对多的关系,这种关系特别适于描述订单中的订单头与订单行的关系。一般来说,每张订单都会对应着若干的订单行,还可以对应付款明细,发货明细等信息。
在WinForm程序中,可以分为两类,一个是SDI模式,另一个是MDI模式,SDI叫做单窗体,MDI叫做多窗体,SDI的典型应用是记事本,打开一个文件后,前面的文件就没有了,而MDI的典型应用是WORD,可以同时打开多个文件进行编辑,互不影响。
在HTML中,连接一般有两种方式,一种是直接替换上一个页面的内容,第二种就是在新窗口中打开,可以理解为对应着CS程序中的SDI和MDI,但是想在同一个IE窗口中打开几个页面是比较困难的,我为了这个功能也是费了很大的力气,最后还是在一些基础控件的基础上做了扩展,实现了真正的MDI的效果,这种效果可以在yahoo邮箱中找到样式。
控件要想有比较好的体现,必须依赖于后台有一个好的数据结构,正是在Meta-Data的驱动模式下,使得这些控件在使用的时候能够得心应用,形成了一个扩展性良好的后台管理部分。下一章就来讲一下如何使用后台及对后台管理部分进行扩展。
本文转自Aicken(李鸣)博客园博客,原文链接:http://www.cnblogs.com/isline/archive/2010/04/17/1714231.html,如需转载请自行联系原作者