由于上面的两个产品不能完全符合我的要求,所以结合jquery-tree以及Telerik treeview设计理念来实现自己的树形菜单是最佳选择。
jquery-tree本身只是一个基于前端的菜单,我们要想传递数据给Controller,唯一比较方便的方法就是通过ajax,但这需要开发人员有比较强的js操纵能力。
Telerik treeview,有点杀鸡用牛刀的意思,Telerik提供了一整UI解决方案,如果我们只用其中的一个功能就引入它,有些不适时宜,但我非常喜欢它给出的思路,它能很好的将View的菜单数据传递给Controller,但Telerik由于提供的是控件,我们不太方便对它的样式做修改,我们更希望能够自由的控制UI显示逻辑。
题外话:关于数据结构
记的有一年,我去一家公司面试,当时估计是技术人员都不在,所以安排了一位年龄上比较大的面试官来面试我,目测应该是位级别不低的领导,当时不免有点小紧张。经过一番自我介绍以及工作经验介绍后,他现场给我出了一道题:
写一个程序,打印出公司的组织结构图,比如最上层是CEO,下面是VP......
我当时跟很大一部分.net程序员一样,做过几年项目后,什么数据结构啊,算法呀早就不记得了,那一刻只想到这是和树相关的数据结构,但不知为何,只想到了二叉树,心想总算想到了,于是开始定义二叉树数据结构,采用递归遍历数据,总之脑袋一片空白,写了一会,领导见我还没写完,有些不耐烦了,问我写完吗,我回答说还差一点,他等了一会见我还没写完,就说先给我看看,于时直接过来拿走我未写完的代码,我是多么的想争取那次机会呀,当时多么的舍不得交出去,最后的结果可想而知。
并不是面试官问的问题有多么难,他考的问题只不过是计算机最基础的东西,而我正好忘记了。到现在我也面试过一些候选人,我也比较注意候选人的基础知识,其实说实在的,像做一些.net相关的企业级开发,大部分情况下我们是不会用到复杂数据结构的,算法就更不用说了,只有少数人会用到这些高级的东西。但这些数据结构以及算法知识会让你的视野更加开阔,在特定情况下能够给你一些方向,如果你对那块领域没有接触过,你是不会朝那方面想的。
这次的树形菜单正好能够解答我以前那位面试官的问题。
树形菜单数据结构:
首先它属于树形数据结构,但不能定义成二叉树,因为一个总裁下面不可能只有两个副总,一个经理下面也不可能只有两个员工,下属应该是大于等于0的数据。
下面是我定义的菜单数据对象:
字段说明:
Text:用于显示的文本,比如:总裁
Value:显示文本对应的ID,比如:0
Index:这个是结合表单的辅助属性,View上使用
Checked:当前菜单项是否被选中,用户提交表单后我们可以通过这个属性判断用户的选择项
Items:当前菜单下的子菜单集合
Parent:当前菜单的上级菜单
HtmlDomName:这个是结合表单的辅助属性,View上使用
树形菜单的输出:
我上次面试过程中的递归逻辑还是有用的,这里我们仍然采用递归来输出菜单项。我创建了一个Partial View
View向Controller的数据传递:
无论是ajax还是直接post表单,最终的目的都是接收View中的数据,要想传递比较复杂的数据类型,我们需要对ASP.NET MVC Model Binding 有一定了解,之前也讲解过MyTreeViewItem的结果,有普通的数据类型,比如 string,bool,也是对象类型,比如MyTreeViewItem类型的Parent,也是基于集合的属性IList<MyTreeViewItem>,要想让表单中的数据直接传递给Controller,我们需要对表单元素的name进行特殊处理才行。如果大家对这部分不太理解,这篇文章可以参考:Understanding-ASP-NET-MVC-Model-Binding
比如我是这样定义Model的:
View:这是主要是加载菜单,至于如何使用jquery-tree,这里就不多说了,大家下可以自己下载demo。
Controller:这是最重要的就是接收参数,它是一个List类型,无论菜单项有多少层,都会按树形数据结构层次组织好,方便我们查询。
UI效果图:下图也是我上次没有回答出来的面试题答案效果图。
下图是Controller接收到的参数:
联系客服