Mvc Tree的简单应用

最近我们的项目中需要用到树型菜单,以前使用WebForm时,树型菜单有微软提供的控件,非常方便,但现在需要在asp.netmvc中使用树形菜单,先说明下我们对树形菜单的需求:
      1:需要支持CheckBox,允许对菜单项进行选择;
      2:当选择父菜单时,它下面的子菜单全部选中;
      3:当取消父菜单的选中状态时,下面的子菜单也全部取消;
      4:要比较方便的与MVC结合。
     
      初步思路:
      思路一:jquery相关的树形菜单插件,由于项目中有应用到jquery,所以不考虑采用其它js框架的产品。
      思路二:asp.net mvc相应的控件,这里指的控制就好比分页控件之类,基本思路就是扩展HtmlHelper来实现,Html逻辑一般都封闭在dll中。
     
      经过一轮筛选后的结果:
     
      思路一:基于js的树形菜单果然有很多,最终我选择了https://github.com/daredevel/jquery-tree,从demo展示来看,它完全能够满足我上面提到的前三个需求。
      思路二:Telerik也有相应的树形菜单控件,它能够很好的结合MVC,最大特点是将View上的树形菜单数据传递给Controller很直观。
     
      最终方案:

由于上面的两个产品不能完全符合我的要求,所以结合jquery-tree以及Telerik treeview设计理念来实现自己的树形菜单是最佳选择。
      jquery-tree本身只是一个基于前端的菜单,我们要想传递数据给Controller,唯一比较方便的方法就是通过ajax,但这需要开发人员有比较强的js操纵能力。
      Telerik treeview,有点杀鸡用牛刀的意思,Telerik提供了一整UI解决方案,如果我们只用其中的一个功能就引入它,有些不适时宜,但我非常喜欢它给出的思路,它能很好的将View的菜单数据传递给Controller,但Telerik由于提供的是控件,我们不太方便对它的样式做修改,我们更希望能够自由的控制UI显示逻辑。
     
       题外话:关于数据结构
       记的有一年,我去一家公司面试,当时估计是技术人员都不在,所以安排了一位年龄上比较大的面试官来面试我,目测应该是位级别不低的领导,当时不免有点小紧张。经过一番自我介绍以及工作经验介绍后,他现场给我出了一道题:
       写一个程序,打印出公司的组织结构图,比如最上层是CEO,下面是VP......
     
      我当时跟很大一部分.net程序员一样,做过几年项目后,什么数据结构啊,算法呀早就不记得了,那一刻只想到这是和树相关的数据结构,但不知为何,只想到了二叉树,心想总算想到了,于是开始定义二叉树数据结构,采用递归遍历数据,总之脑袋一片空白,写了一会,领导见我还没写完,有些不耐烦了,问我写完吗,我回答说还差一点,他等了一会见我还没写完,就说先给我看看,于时直接过来拿走我未写完的代码,我是多么的想争取那次机会呀,当时多么的舍不得交出去,最后的结果可想而知。
     
      并不是面试官问的问题有多么难,他考的问题只不过是计算机最基础的东西,而我正好忘记了。到现在我也面试过一些候选人,我也比较注意候选人的基础知识,其实说实在的,像做一些.net相关的企业级开发,大部分情况下我们是不会用到复杂数据结构的,算法就更不用说了,只有少数人会用到这些高级的东西。但这些数据结构以及算法知识会让你的视野更加开阔,在特定情况下能够给你一些方向,如果你对那块领域没有接触过,你是不会朝那方面想的。

这次的树形菜单正好能够解答我以前那位面试官的问题。
     
      树形菜单数据结构:
      首先它属于树形数据结构,但不能定义成二叉树,因为一个总裁下面不可能只有两个副总,一个经理下面也不可能只有两个员工,下属应该是大于等于0的数据。
      下面是我定义的菜单数据对象:

public class MyTreeViewItem
    {
        public IList<MyTreeViewItem> Items { get; set; }
        public string Value { get; set; }
        public bool Checked { get; set; }
        public string Text { get; set; }
        public string Index { get; set; }
        public MyTreeViewItem Parent { get; set; }
        public string HtmlDomName { get; set; }
    }

字段说明:
       Text:用于显示的文本,比如:总裁
       Value:显示文本对应的ID,比如:0
       Index:这个是结合表单的辅助属性,View上使用
       Checked:当前菜单项是否被选中,用户提交表单后我们可以通过这个属性判断用户的选择项
       Items:当前菜单下的子菜单集合
       Parent:当前菜单的上级菜单
       HtmlDomName:这个是结合表单的辅助属性,View上使用
      
       树形菜单的输出:
       我上次面试过程中的递归逻辑还是有用的,这里我们仍然采用递归来输出菜单项。我创建了一个Partial View

@model MvcTreeView.Controllers.MyTreeViewItem
<ul>
    <li>
        @if (null == Model.Parent)
        {
            Model.HtmlDomName = "TreeView1_checkedNodes[" + Model.Index + "]";
        }
        else
        {
            Model.HtmlDomName = Model.Parent.HtmlDomName + ".Items[" + Model.Index + "]";
        }
        <input name=‘@(Model.HtmlDomName + ".Checked")‘ type="checkbox" onchange=‘setValue(this)‘  value=‘False‘ />
        <input  name=‘@(Model.HtmlDomName + ".Text")‘ type="hidden" value="@Model.Text" />
        <input  name=‘@(Model.HtmlDomName + ".Index")‘ type="hidden" value="@Model.Index" />
        <span>@Model.Text</span>
        <input  name=‘@(Model.HtmlDomName + ".Value")‘ type="hidden"
                                        value="@Model.Value" />
        @if (null != Model.Items)
        {
            for (var i = 0; i < Model.Items.Count; i++)
            {
            @Html.Partial("NodeItem", Model.Items[i])
            }
        }
    </li>
</ul>

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的:

public class AboutModel
    {
        public MyTreeViewItem NodeItem { get; set; }

}

View:这是主要是加载菜单,至于如何使用jquery-tree,这里就不多说了,大家下可以自己下载demo。 

@using (Html.BeginForm())
{
    <div id="accordion">
        <h3>
            <a href="#">All components in default behaviour</a></h3>
        <div id="example-0">
            <div>
             @if (null != Model.NodeItem)
            {
                @Html.Partial("NodeItem", Model.NodeItem)
            }
             
            </div>
        </div>
    </div>
    <input type="submit" id="example-0-button" />
}

Controller:这是最重要的就是接收参数,它是一个List类型,无论菜单项有多少层,都会按树形数据结构层次组织好,方便我们查询。

[AcceptVerbs(HttpVerbs.Post)]
        public ActionResult About(List<MyTreeViewItem> TreeView1_checkedNodes)
        {
            return View(this.GetAboutModel());
        }

UI效果图:下图也是我上次没有回答出来的面试题答案效果图。

下图是Controller接收到的参数:

   

原文地址:https://www.cnblogs.com/guoyu8/p/9834691.html

时间: 2024-10-13 04:51:18

Mvc Tree的简单应用的相关文章

使用TT模板+mvc+wcf实现简单查询

伴随着春姑娘调皮的脚步,小编接手的档案管理项目也渐渐步入正轨,从开始的需求分析,到使用Axure画原型图,再到使用powerdesigner设计实体,生成数据库,一直到昨天刚刚通了一条线,这一路走来,小编懂得了很多,无路学习还是和团队小伙伴的交流合作,有时候,总是会因为大家意见不统一,搞的大家吹胡子瞪眼,但有时也会因为某件事情圆满成功而欢欣鼓舞,小组中最开心的事儿莫过于有人开会迟到买吃的了,哈哈,暴露了小编的本质,开头说了这么多,接下来,小编就跟分享一下,如果利用TT模板+mvc+wcf实现简单

支持泛型AVL Tree的简单实现,并和STL map比较了插入,删除,查找的性能

1.问题描述: 1)AVL tree是一种自平衡树.它通过左右子树的高度差来控制树的平衡,当高度差是不大于1的时候,认为树是平衡的.树的平衡保证了树在极端情况下 (输入序列不够随机)的性能.很显然当左右子树高度平衡,保证了任何插入,删除,查找操作平均性能呢个,当不平衡时(有的子树很高),当 要操作的元素在这个子树时,性能会很差: 2)AVL tree 和Red black tree 都是一种平衡树,它的操作的时间复杂度是:O(lgN) ,N是树的节点的数目: 3)本文实现了AVL Tree, 并

Spring MVC +MyBatis +MySQL 简单的登录查询 Demo 解决了mybatis异常

忙活了大半天,饭也没顾得上吃,哎许久不动手,一动手就出事,下面请看今天的重头戏,额吃个饭回来再发了! 1.整体结构 2.准备工作 数据库: --Mysql 5.6 创建数据库 wolf CREATE DATABASE wolf; 创建用户表 user create table user( id int  AUTO_INCREMENT  primary key, name varchar(25) not null, pwd varchar(20) not null, create_time dat

在 asp.net mvc中的简单分页算法

//第一步:建立如下分页实体类:namespace MVCPager.Helpers { /// <summary> /// 简单分页算法类 /// </summary> public class Pager { public int RecordCount { get; set; } public int PageIndex { get; set; } public int PageSize { get; set; } public int PageCount { get { r

MVC其实很简单(Django框架)

Django框架MVC其实很简单 让我们来研究一个简单的例子,通过该实例,你可以分辨出,通过Web框架来实现的功能与之前的方式有何不同. 下面就是通过使用Django来完成以上功能的例子: 首先,我们分成4个Python的文件,(models.py , views.py , urls.py ) 和html模板文件 (latest_books.html ). models.py: # models.py (the database tables) from django.db import mod

ASP.NET MVC 及 Areas 简单控制路由

ASP.NET MVC中怎么去控制路由,这个想关的文章很多,我在这里就是自我总结一下,仅供参考. 1.我们新建一个项目,查看RouteConfig.cs,代码如下: 1 public static void RegisterRoutes(RouteCollection routes) 2 { 3 routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 4 5 routes.MapRoute( 6 name: "Default&quo

SpringSecurity 在MVC 中的简单使用(翻译的,稍加改动)

Spring Security允许开发人员轻松地将安全功能集成到J2EE Web应用程序中,它通过Servlet过滤器实现“用户自定义”安全检查. 在本教程中,我们将向您展示如何在Spring MVC中集成Spring Security 3.0并安全访问.在集成成功后,当我们查看页面的内容时用户需要先输入正确的“用户名”和“密码”. 1.目录结构 项目最终目录如下所示: 2.Spring Security依赖关系 为了正常运行 Spring security , 你需要加入 “spring-se

ASP.NET MVC ViewData/ViewBag 简单小结

近期在项目中遇到一个问题,就是用ViewBag.Model存储匿名对象传递给View,但是需要根据条件给匿名对象添加属性,这个可真心不易,Google了一下发现很多方案都是动态编译神马的,感觉好高大上,最后也没采用,因为不知道动态编译的性能消耗大不大. 最后是自己简单研究了一下,在ViewBag.Model中存储了Dictionary<string, object>,在View通过Model[key]的方式可以正常读取相应的值,在此对ViewData和ViewBag的使用进行一个简单的小结:1

cocos2dx之lua项目开发中MVC框架的简单应用

**************************************************************************** 时间:2015-03-31 作者:Sharing_Li 转载注明出处:http://blog.csdn.net/sharing_li/article/details/44658317 **************************************************************************** 最近的游