功能导航主要解决如何布局功能,把功能如何合理的布置到页面中。现在流行的一种方案是左右结构的导航,左边树状的菜单,右边显示明细功能。实现出来的效果图如下所示
同版本的C/S程序的界面,也是以同样的效果出现
Web左边点击树节点,右边打开相应的功能列表,显示该节点下面有哪些功能。而这些功能节点,均是用菜单设计器设计实现,以方便客户定制主界面。菜单设计器的设计样式如下
关于如何实现树节点的母子关系,有很多办法。一种办法是给树的每个节点加一个ParentId,用于指示它的上一级节点,这样每设计一个节点,均需要指出它的父节点,以用于呈现母子关系。另一种方法,以本例子中实现为例子,1002为Sales的树节点,它的子节点全部用1002XX来标识,如上图中所示,100201表示日记帐,100202表示报表,100203表示查询。前一种方法,请参考框架数据库中的表X_Menu,后一种请参考表UserGroupMenu。
导航的另一个目的,要实现中英文自动切换,以方便不同的用户习惯偏好。Enterprise Solution系列的组件,均内置了中英文切换的功能,可以在Settings中,选择习惯的语言进行设置。对于Web应用程序,用户的语言偏好保存在浏览器的Cookie中,对于C/S程序,用户的语言偏好保存在注册表中。
再来看看,如何快速的找到需要的功能,并打开执行它。如果您习惯在左边的菜单中查找,则可以直接在菜单对应的右边的功能列表区域中,打开该功能。另一种方法是,在快速启动栏中输入功能编码,点击Go按钮,此时,它会在新的选项中页面中,打开此功能。一般来说,系统预置了三种类型的功能
- 页面功能
- 报表
- 自定义查询
如何让一个ASP.NET页面成为功能点,并自动被系统框架找到呢? 请参考下面的例子代码
[Function("AIITRL", "~/module/note.aspx")] public partial class note : EntryPageBase { protected override void PageLoadEvent(object sender, EventArgs e) { if (!IsPostBack) TransactionType = "BlotterEntity"; base.PageLoadEvent(sender, e); } }
给页面加Function特性,第一个参数是功能编码,第二个参数是页面的绝对地址。当在快速启动栏中输入AIITRL时,框架会找到(反射)此页面,并在新的选项卡页面中打开加载此功能。
这里要提到一点不足,对于ASP.NET,它是被浏览器请求执行。不同于C/S,可以new一个窗体,然后Show。我一直在寻找一种方法,可以通过页面的类型,来找到这个页面所在的aspx文件地址,这样可以省略Function特性的第二个参数,到目前一直没有找到可行的方案。第二个参数可以通过菜单设计器来辅助完成,不过原理和这里的差不多,也是人工识别,所以,我直接把地址放在特性参数中,以用于导航。
第二类功能是报表。先在报表设计器中设计此报表,给予一个编号,参考如下图所示
在报表设计窗体中,给予基本的参数。然后在Web项目的report目录中,放置报表文件。理论上,需要支持三大流行的报表系统。RDLC,微软客户端报表,简单,易用,Crystal Report 水晶报表,功能复杂强大,Reporting Services 微软服务器端报表。Enterprise Solution Web部分,目前只实现了RDLC客户端报表,其它二项报表的功能,还有待研究和实现。这里要提到一点,加入一种类型的报表,要实现如下的基本功能:
1 多语言 基本的中,英,繁体
2 多种版本。Crystal Report 有多种版本,要能识别各个版本的报表文件并加载合适的呈现器(Render)
3 界面输入与传值。有的报表需要传递参数,系统要创造界面输入值,并自动的传入到报表中
第三类功能是自定义查询。用户在查询设计器中设计的查询,Web框架要能解析成界面,呈现给用户。
在此设计的查询,通过在快速启动栏中输入PUPRSQ功能编码,呈现给用户如下效果的界面
查询的结果,可以导出为EXCEL。关于如何将query转换为Web界面,在后续的文章中会讲解原理,在此先略过。
导航功能的好坏,对系统的可用性,有一定的影响。试想一下,功能很复杂的一个系统,用户要找一个功能,要找很久都找不到,或是没有快捷的途径找到它,用户肯定不会认为它好用。其次,快速启动栏的设计,用一个功能编码标识用户需要的一个功能模块,有利于用户快速执行所需要的功能。高级的用户不想去树节点中找,则可以此方法执行功能。
最后,导航菜单是可编辑的,提供一个菜单编辑器,随心所欲的设计用户所需要的效果。