最近封了一个简单的类库,主要目的是帮助实现简化制作表单页面的工作。使得制作一个具有提交、修改、浏览功能的表单页面,只需要摆好控件再写很少量的代码即可。在需求发生变动需要调整UI的时候,也仅是调整控件的摆放而已。而且还可以根据工作的流程制作多套表单,在实际使用的时候,根据流程不同来动态切换。这里发个简单的Demo,实际要比这复杂一些,但是Demo已足够阐述实现原理,目的也就达到了。
下面做简单的介绍,具体看代码。(代码是ASP.Net2.0/VS2005的,在C/S里的实现,原理也是一样的。)
约定: 1.表单上的控件ID名称需要同对应的实体的数据字段名相同。(以此为依据映射数据)
一、使用步骤: 1、引用Justin.UILibrary.dll; 2、添加一个用户自定义控件DemoUI.ascx; 3、摆放表单控件,简单演示如下图: 红色部分为自定义校验控件,这里只是个演示,实际中怎么弄随便了。 4、修改用户控件的代码如下: 5、到此,一个只管收集数据,显示数据,修改数据的UI用户自定义界面就做好了。下面需要在页面上使用这个用户自定义控件。Go on … 6、在页面需要显示这个表单的地方放一个PlaceHolder控件,这么做是为了可以动态加载用户自定义控件,从另一个角度来说,这也实现了动态替换不同的用户自定义控件功能,比如你有多个表单需要在不同的情况下动态切换,那么,使用PlaceHolder控件,再配合XML配置文件,一切就OK了。 7、然后在页面的*.aspx.cs里添加如下代码: 8、Ctrl+F5执行程序,一切就OK了!
二、效果演示: a、提交的时候(除了下拉框,其它都为空): b、浏览的时候(所有控件不可用) c、修改状态(界面上有数据,为待编辑状态) 三、Deom总结 最后画了一个简单的顺序图,说明一下程序内部是如何执行的。其中,关于XML的部分在Demo里没有做,只是用注释标明了一下,这个很简单,但是功能却很强大,可以让你在运行时动态决定界面加载哪个预定义的表单用户自定义控件,所以有必要在图中画了一下。 四、关于Justin.UILibrary.dll 最后我们再简单说一下Justin.UILibrary.dll,有了它,使得制作表单的大部分工作变成了摆控件,它把报单里可以抽出来的东西尽量都封装了起来,使得大部分代码工作都得到了重用。这里简单说一下最核心的UI.cs类,它是表单控件的基类,如上面的步骤4所示,继承它之后,只需要附加很少的代码,即可以完成表单的后台代码工作。当然,这里提供的都是最基本的功能,如果用户自己有任何其他字定义功能,都可以自己在继承的基础上再进行扩展。 其中比较关键的几个地方是: 1.ExecActionEvent()方法 这个方法使用委托的机制,将最终按钮的功能如何实现抛出来由用户自己去实现,WHY?因为鬼才知道用户会做什么,这是封装控制不了的因数,所以要抛出去。 2.InitControl(UIType type)方法 这里相当于模板方法模式的应用,内部在不同状态下调用的三个virtual方法,给了SubCalss一个插入功能的机会,即,可以分别在提交、浏览、修改的状态下初始化界面时,加入自定义的功能。如步骤4中所做的,在提交的时候,将按钮的标题改为“提交”,在修改的时候,将按钮的标题改成“保存”,当然,用户自己还可以做很多别的什么事情,这个灵活性是封装的基类不去关心的,基类只提供“工作机会”,至于工作的怎么样,自己看着办吧。 如下图所示: 五、代码下载 JustinDemo: http://files.cnblogs.com/justinw/JustinDemo.rar Justin.UILibrary: http://files.cnblogs.com/justinw/Justin.UILibrary.rar
虽然这里还只是演示代码,部分地方还有待完善,但是这篇文章主要想说的是如何通过封装来重用和简化代码工作,重要的是其中的原理和思想,还希望各位朋友看过代码后多提宝贵意见。
posted on 2006-10-04 10:02 Justin 阅读(3544) 评论(18) 编辑 收藏 所属分类: Practice 、Design Patterns
好,学习一下 回复 引用 查看
看起来封装的不错,下个代码学习学习 回复 引用 查看
这几天还在构思一个post,就上将拖拽进行到底,呵呵 看过楼主的文章后眼睛真的有一亮的感觉 回复 引用 查看
@aspnetx @壮志 @phinecos(洞庭散人) 多提宝贵意见~ 回复 引用 查看
不错,希望以后有更多这样的东西摆出来给大家共享 回复 引用 查看
@代码乱了 me too 回复 引用 查看
谢谢,认真拜读了Justin Wang 兄的文章和源代码后,启发颇多.谢谢! 提个小小的意见: FormConvertUtils.cs类中有两个方法,一个是将UI数据统一收集的Hashtable中(UI2Data),另一个是将Hashtable中的数据统一初始化到UI上面(Data2UI),实现的机制都是用循环递归的方法,这个似乎会很影响效率.有没有其他更高的实现机制? 回复 引用 查看
@老夫子系 谢谢支持! 恩,关于你说的问题,怎么说呢,这可能是一个权衡的问题,抽象和效率大多数时候是矛盾的对立,很难两全。 从抽象角度说:如果你站在高度抽象的角度去思考问题,你的代码就不能去对任何个性的东西产生依赖,例如UI2Data和Data2UI两个方法,因为前提是第一我们不去考虑UI上有多少控件,这样就需要Foreach循环,第二,我们不去考虑这些控件是如何嵌套的,一个Textbox外面套了100个Panel我也不管,但是代码要支持正确取值和赋值,所以这里就需要递归。这样,就可以支持大部分的界面了,随他怎么摆,代码不需要修改就可以支持。 从效率的角度说:缩小循环的范围,保证控件只摆在一层上,就象Demo里一样,这肯定会提高效率的。但是这个效率提高不见得会很明显。 最后,如果真是遇到一个嵌套了N层,每层N多控件的表单的话,即使循环递归也应该不是太糟糕的办法,要不,这么大的数据量,怎么做才有效率呢?呵呵,还是矛盾的~ 回复 引用 查看
mark一下。 回复 引用 查看
小弟提出些肤浅的见解,望大哥指导指导: 类库封装的非常棒,但好像没有齐全,因为要是作为类库用,最好不好老动,以免出现问题! 小弟认为提交表单写成这样好像不是很有必要,不知道大哥能否给小弟解释下,在这先多谢了! 回复 引用 查看
@Bryant 先谢谢你的留言,很高兴能回答你的问题! 关于第一个问题:没有封装完全? 恩,怎么说呢,其实这里确实还有很多东西可以封,比如UI2Data和Data2UI的功能,依赖于控件类型,实际使用的时候,可能需要针对控件上面的特定控件类型进行调整,这确实不是一个好办法,如果想再封装的更完美一些,可以把控件类型做成XML可配置文件,然后使用依赖注入的方式(或其他方法)来跟具体控件类型解偶。但是,基于这篇文章,重点的是通过实例讲封装的一些原理和思想,毕竟代码都是演示性质的,没有经过太多的打磨和验证。 关于第二个问题:提交表单不需要封装? 嘿嘿,如果你需要的只是一两个表单,确实没有封装的必要,直接写就行了,用最直接最简单的方法,做出来的同样是好东西。而假如你需要十几个或几十个表单,而且表单上还有十几个或几十个不同类型的控件,那么你每个都直接写就太麻烦了吧,这时你可能就很渴望有封装了,而且不需要再每一个控件去赋值什么的,多爽啊!哈哈 上面只是做了简单的解释,其实封装的好处还很多,代码重用是一方面,更重要的是保证了代码的健壮性,还有统一修改等等,还有就是OO里面的职责分配原则,比如这里的UI,它只管收集数据,显示数据,至于数据从那来,去那里,这些它都管不着,也不该管,嘿!慢慢体会吧~ 回复 引用 查看
能不能提供你的联系方式?? 回复 引用
@hehe 页面右上角的公告里有我的mail,代码注释里有我的MSN~ 回复 引用 查看
很开心,非常谢谢你这么迅速的回复! 我在你的代码注释里好像没有看见你的MSN 这里是我的MSN:smwang_2005@hotmail.com 多多指导! 回复 引用 查看
@Bryant 嘿嘿!相信你应该已经发现了! 回复 引用 查看
代码还是太多了一点。呵呵。 XML配置文件要手动维护吗?你有些一个文化程序的想法吗? 对于不同类型的控件你是怎么处理的呢?比如 TextBox DropDownList Check等。 回复 引用 查看
@金色海洋(jyk) 哦,就这篇文章,并没从代码多少的角度深入考虑,我认为重用是根本目的,代码多少是次要的因素。 这是XML配制文件,而不是实体映射文件,可以根据数据库做成自动生成的,配置的东西,省不掉吧 如果你看过代码,应该知道怎么处理的不同控件,注释里也有对应描述,上面的留言里也有相关的讨论~ 谢谢支持! 回复 引用 查看
楼主是高手 回复 引用