MVC3小技巧09(MVC3树形控件)

-
引言

MVC3 提供了基于jQuery、jQuery UI的基础应用,缺少许多常用的组件,例如:页面布局、导航菜单、树形、日期时间等等。

03-树形控件

MVC3 没有提供树形控件,很多初学者到处寻找MVC3 Razor 引擎使用的树形控件,可能无奈之下选择了Telerik、Devexpress、ComponentOne等整套开发组件,又是一个从头学习的开始。

这种开发组件,有它的很优秀的特点:

1)提供基本完整的开发资源:多种皮肤、消息提示、对话框、编辑窗口、菜单、树形、网格(内置工具栏)、日期时间、选项卡、下拉框、上传文件等等,语法一致。

2)使用这样的开发组件也会形成一个群体,可以找到很多资源可供参考。

这种开发组件,弊端也是非常明显:

1)加载体积庞大或者数量众多的 JSCSS 文件

2)一般需要安装程序,提供相当数量的dll来支持运行环境

3)是否能够最快地产生纯净的HTML代码,DIV+CSS提供最快的运行程序?

其实,我们需要深刻理解微软为什么提供 MVC3 + EF4 这种开发框架,而又不提供大量的开发控件给程序员。其实,我们想一想:微软有着世界上最优秀的开发团队,怎么不能提供类似ASP.NET WebForm的大量控件给我们使用?当然能,而且能够做得更好!

但是,微软看到了基于 jQuery、jQuery UI开发群体的庞大和jQuery框架的优点,最终提供给我们一种更简洁的Razor引擎的语法+jQuery的开发模式,那就是MVC3。

我感觉到,微软是想让我们抛掉过去使用现成开发组件的习惯,MVC3可以把程序员引领到研发者的团队中来

废话啰嗦了一大堆,回过头,接着说MVC3怎么使用树形控件?

我们可以选择jQuery的控件+CSS,结合MVC3的优点,生成纯净的HTML代码,快速、高效。

介绍一个JS树形控件:jquery.dynatree.js,目前版本是1.1.1

这种树形控件功能很完善,常见的应用都提供了,而且,已经被用在MVC3开发框架上了,非常好用。

采用JSON格式的数据源,格式:

key、title、url、isFolder、isLazy、expand、select、children

1)不带选择框的数据源

            [
                {title: "Item 1"},
                {title: "Folder 2", isFolder: true, key: "folder2",
                    children: [
                        {title: "Sub-item 2.1"},
                        {title: "Sub-item 2.2"}
                    ]
                },
                {title: "Item 3"}
            ]
2)带选择框的数据源

    var treeData = [
        {title: "item1 with key and tooltip", tooltip: "Look, a tool tip!" },
        {title: "item2: selected on init", select: true },
        {title: "Folder", isFolder: true, key: "id3",
            children: [
                {title: "Sub-item 3.1",
                    children: [
                        {title: "Sub-item 3.1.1", key: "id3.1.1" },
                        {title: "Sub-item 3.1.2", key: "id3.1.2" }
                    ]
                },
                {title: "Sub-item 3.2",
                    children: [
                        {title: "Sub-item 3.2.1", key: "id3.2.1" },
                        {title: "Sub-item 3.2.2", key: "id3.2.2" }
                    ]
                }
            ]
        },
        {title: "Document with some children (expanded on init)", key: "id4", expand: true,
            children: [
                {title: "Sub-item 4.1 (active on init)", activate: true,
                    children: [
                        {title: "Sub-item 4.1.1", key: "id4.1.1" },
                        {title: "Sub-item 4.1.2", key: "id4.1.2" }
                    ]
                },
                {title: "Sub-item 4.2 (selected on init)", select: true,
                    children: [
                        {title: "Sub-item 4.2.1", key: "id4.2.1" },
                        {title: "Sub-item 4.2.2", key: "id4.2.2" }
                    ]
                },
                {title: "Sub-item 4.3 (hideCheckbox)", hideCheckbox: true },
                {title: "Sub-item 4.4 (unselectable)", unselectable: true }
            ]
        }
    ];
上面这个数据源,包含了怎么禁用选择、怎么隐藏选择框、怎么初始化激活节点、展开节点、工具提示等。

3)带地址链接的数据源

            [
                {title: "Search engines", isFolder: true, expand: true,
                    children: [
                        {title: "Google", url: "http://www.google.com"},
                        {title: "Yahoo", url: "http://yahoo.com"}
                    ]
                },
                {title: "jQuery", isFolder: true, expand: true,
                    children: [
                        {title: "jQuery", url: "http://www.jquery.com"},
                        {title: "jQuery UI", url: "http://jqueryui.com"},
                        {title: "API browser", url: "http://api.jquery.com"},
                        {title: "dynatree", url: "http://code.google.com/p/dynatree/"}
                    ]
                },
                {title: "Misc", isFolder: true, expand: true,
                    children: [
                        {title: "Welcome", url: "sample-iframe-1.html"}
                    ]
                }
            ]
当然,单击链接,弹出窗口打开链接,如果想要在当前页面内显示,请使用iframe,或者内部链接用DIV显示网页内容

dynatree-doc.html包含常用的各种属性和事件

常用属性,举例说明

        var tree = $("#tree");
        tree.dynatree({

            checkbox: false,// 是否显示选择框
            clickFolderMode: 3,// 单击目录:1-激活, 2-展开, 3-激活并展开
            selectMode: 1,// 选择模式:1-单选, 2-多选, 3:级联多选
            strings: { loading: "正在加载…", loadError: "加载失败!" },// 加载提示
            initAjax: { url: "/System_Area/InitTree" }, // 初始化数据请求
            onPostInit: function (isReloading, isError) {// 初始化请求结束,呈现网页前
            },
            onLazyRead: function (node) {// 延迟加载下级节点
            },
            onActivate: function (node) {// 激活节点
            },
            onDblClick: function (node) {// 双击节点
            }
        });
    });
当然,支持拖放调整树形,具体自己看官方提供实例。

一般我们会添加一个动态树形节点类:
    public class DynamicTreeNode
    {
        public string key { get; set; }
        public string title { get; set; }
        public bool expand { get; set; }
        public bool isFolder { get; set; }
        public bool isLazy { get; set; }
        public bool select { get; set; }
        public List<DynamicTreeNode> children { get; set; }
    }

控制器接收AJAX请求,建议使用EF4.1查询数据:

 List<xxx> list = (from p in db.System_Areas
                                            select new System_Area_Tree() { AreaCode = p.AreaCode, AreaName = p.AreaName, ParentCode = p.ParentCode }).ToList();

添加一个生成树形节点的方法,业务不同,字段也不一样,自己编写这么一个类似的方法:

        /// <summary>
        /// 创建节点
        /// </summary>
        /// <param name="list">数据源</param>
        /// <param name="parentNode">上级节点</param>
        /// <returns></returns>
        public DynamicTreeNode CreateNode(List<xxx> list, DynamicTreeNode parentNode)
        {
            List<xxx> rows;
            string parentCode = parentNode.key;
            bool root = *;//判断是否根节点
            if (root)
            {
                rows = list.Where(*)).OrderBy(*).ToList();
            }
            else
            {
                rows = list.Where(*).OrderBy(*).ToList();
            }
            if (rows.Count() > 0)
            {
                parentNode.children = new List<DynamicTreeNode>();
            }

            foreach (var row in rows)
            {
                DynamicTreeNode itemNode = new DynamicTreeNode();
                itemNode.key = row.xxxCode;
                itemNode.title = row.xxxName;
                List<xxx> subs = *;// 获取下级节点
                if (subs.Count() == 0)
                {
                    parentNode.children.Add(itemNode);
                    continue;
                }

                itemNode.isFolder = true;
                parentNode.children.Add(CreateNode(list, itemNode));
            }

            return parentNode;
        }

这个方法,我删除了限制层级的代码,延迟加载一般只需要加载下面一级子节点,限制层级就有必要了。

调用这个方法,返回JSON数据:

JsonResult jsonResult = new JsonResult() { JsonRequestBehavior = JsonRequestBehavior.AllowGet };
jsonResult.Data = CreateNode(list, rootNode);

前端 initAjax: { url: "/System_Area/InitTree" } 发出的初始化请求,自动会初始化数据。

如果初始化完成,还需要加载网格数据,一般在 onPostInit 事件中处理,或者直接AJAX请求网格数据,和树形初始化并发进行效率要高一些

如果这棵树是带选择框的,那么就需要保存数据,举例说明:

        $('#save').click(function () {

            // 获取选择内容
            var checked = menu.dynatree("getSelectedNodes");
            。。。
            // 保存当前数据
            $.ajax({type:'post', url: '*', data: *...});
        });
讲了这么多,不知道你们听明白了没有。其实,你只要看开发包的实例,就能明白怎么使用了。动态树形1.1.1开发包见这里下载

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值