• ASP.MVC EASY UI 入门之 —— Tree & ComboTree


    1、常规的EASY UI的tree和comboTree代码基本是官方的DEMO都有的,虽然很简单,但是还是要实践的做一次,才能更清晰的了解和使用它!先上效果图

    因为用的是code first,所以数据库的MODEL我是这样做的,这里面注释了许多,是再设计表结构的时候走的弯路和一些备用的东西。

    关键的是ID自己的唯一标示,PID是所属的父级,无非就是一个递归表,也就是无极分类表。当然,这是设计的问题。

    其次是显示的文字和点击文字后进入的一些操作。这里我只做了一个显示的文字TEXT还有点击文字后进入的相应链接。这里还可以加入显示的图片等内容!

    Menu是数据库的结构,但是我们的tree和ComboTree需要的数据并非数据库里原样的数据,所以,我们针对他们需要的数据设计了2个类。

    treedata就是他需要的数据的具体形式。其中attribute就是每个节点里需要的具体内容。参考EASYUI的DEMO和文档,我设计的这2个类。

    namespace TOM.Model
    {
        public class Menu
        {
            [Key]
            [Required]
            public int ID { get; set; }
            public int? PID { get; set; }
            [Required]
            [MaxLength(100)]
            public string Text { get; set; }
            [StringLength(255)]
            public string URL { get; set; }
    
            //[ForeignKey("PID")]
            //public virtual Menu Parent { get; set; }
            //public virtual ICollection<Menu> Children { get; set; }
        }
        [NotMapped]
        public class TreeData
        {
            //id: An identity value bind to the node.
            public string id { get; set; }
            //text: Text to be showed.
            public string text { get; set; }
            //state: The node state, 'open' or 'closed'.
            public string state { get; set; }
            //iconCls: The css class to display icon.
            public string iconCls { get; set; }
            //attributes: Custom attributes bind to the node.
            public attribute attributes { get; set; }
            //pid: string, parent id
            public string pid { get; set; }
            ////checked: Whether the node is checked. 
            ////public string @checked{get;set;}
            //[DataMember(Name = "checked")]
            //public string ischecked { get; set; }
            ////attributes: Custom attributes bind to the node.
            //public Dictionary<string, object> attributes { get; set; }
            //public List<TreeData> children { get; set; }
            ////target: Target DOM object.
        }
        [NotMapped]
        public class attribute
        {
            public string url { get; set; }
            //other data
        }
    }

    在EASY UI中,应该就是只有异步树的。当然,你如果按照官方要的数据一次性全都查出来,那么就是同步树了。

    每个节点都有一个点击事件,每次点击Tree就会默认的Post一个id给后台(当然是异步的时候,如果已经获取到数据了,它就不在POST)。

    这里我做了2个事件。onClick事件,获取到的是节点数据。

    此外,还有一个onLoadSuccess,这个是完成异步树的过程,它的任务是这样的,默认我们访问后台数据的时候,首先是'/Menu/AsyncTree',仅仅是一个URL,木有参数

    [HttpPost]
    public JsonResult AsyncTree(int id = 0)

    默认的是给0,那么,也就是先把第一级树节点查出来。

    然后,当onLoadSuccess相应的时候,它会判断当前的节点是否有子节点(this.state == 'closed' 有子节点的节点,其状态是closed),如果有子节点,通过 t.tree('expandAll');就会展开这个子节点,那么如果这个子节点下的数据未被获取到,Tree就会默认的POST当前节点的id给后台,让后台去加载其子节点数据,相当于代替人工去click子节点。

    也就是说,如果我们加入onLoadSuccess事件,并且通过this.state和 t.tree('expandAll')这2个关键操作,就能够实现异步的,一次性全部加载完毕所有的树(递归)。

    如果我们不加入onLoadSuccess事件,也是可以的,那就是真正意义和形式上都是异步的。每次点击节点,如果节点状态是'closed',且,其子节点数据并没有加载,那就Tree就会Post一个ID给后台。

                //-----------异步树-------------------
                $('#AsyncMenu').tree({ 
                    url: '/Menu/AsyncTree',
                    lines: true,
                    checkbox: true,
                    //异步树的点击事件
                    onClick: function (node) {
                        if (node.attributes == undefined) {
                            return;
                        }
                        if (node.attributes.url && node.attributes.url.length > 0) {
                            var src = node.attributes.url;
                            $.messager.alert('提示', '[' + src + ']!', 'info');
                        }
                    },
                    //异步树全部自动展开
                    onLoadSuccess: function (node, data) {
                        var t = $(this);
                        if (data) {
                            $(data).each(function (index, d) {
                                if (this.state == 'closed') {
                                    t.tree('expandAll');
                                }
                            });
                        }
                    }
                });

       前台的HTML这样写就可以

        <fieldset>
            <legend>异步树</legend>
            <ul id="AsyncMenu"></ul>
        </fieldset>

    此外,国人也有高手,扩展了这2个组件,使其支持,ID,PID这样的平滑结构。也就是说,不需要递归,只需要把数据全部一次性的读出来,由扩展方法来完成其节点和子节点的关系映射。节约了不少代码,当然,它就不是异步树了。扩展代码如下。

    var sy = sy || {};
    /*
    * * 扩展tree和combotree,使其支持平滑数据格式 * * @author 孙宇 * * @requires jQuery,EasyUI * */ sy.loadFilter = { loadFilter : function(data, parent) { var opt = $(this).data().tree.options; var idField, textField, parentField; if (opt.parentField) { idField = opt.idField || 'id'; textField = opt.textField || 'text'; parentField = opt.parentField || 'pid'; var i, l, treeData = [], tmpMap = []; for (i = 0, l = data.length; i < l; i++) { tmpMap[data[i][idField]] = data[i]; } for (i = 0, l = data.length; i < l; i++) { if (tmpMap[data[i][parentField]] && data[i][idField] != data[i][parentField]) { if (!tmpMap[data[i][parentField]]['children']) tmpMap[data[i][parentField]]['children'] = []; data[i]['text'] = data[i][textField]; tmpMap[data[i][parentField]]['children'].push(data[i]); } else { data[i]['text'] = data[i][textField]; treeData.push(data[i]); } } return treeData; } return data; } }; $.extend($.fn.combotree.defaults, sy.loadFilter); $.extend($.fn.tree.defaults, sy.loadFilter);

    这样一来,我们使用就相当方便了

      //----------Tree扩展方法(非异步,支持【id,pid】格式)---------------
    
                $('#ExtMenu').tree({
                    url: '/Menu/ExtTree',
                    //指定父节点字段
                    parentField: 'pid',
                    lines: true,
                    checkbox: true,
                    //点击事件
                    onClick: function (node) {
                        if (node.attributes == undefined) {
                            return;
                        }
                        if (node.attributes.url && node.attributes.url.length > 0) {
                            var src = node.attributes.url;
                            $.messager.alert('提示', '[' + src + ']!', 'info');
                        }
                    }
                });
            });

    前台HTML代码这样写

        <fieldset>
            <legend>ComboTree</legend>
            <div style="margin: 10px 0">
                <a href="javascript:void(0)" class="easyui-linkbutton" onclick="getValue()">GetValue</a>
                <a href="javascript:void(0)" class="easyui-linkbutton" onclick="setValue()">SetValue</a>
                <a href="javascript:void(0)" class="easyui-linkbutton" onclick="disable()">Disable</a>
                <a href="javascript:void(0)" class="easyui-linkbutton" onclick="enable()">Enable</a>
            </div>
            <select id="ComboTree" class="easyui-combotree" style=" 200px;"
                data-options="url:'/Menu/ExtTree',required:true,parentField: 'pid',value:'1'">
            </select>
        </fieldset>

     辅助的几个JS方法如下:

            function getValue() {
                var val = $('#ComboTree').combotree('getValue');
                $.messager.alert('提示', '[' + val + ']!', 'info');
            }
            function setValue() {
                $('#ComboTree').combotree('setValue', '2');
            }
            function disable() {
                $('#ComboTree').combotree('disable');
            }
            function enable() {
                $('#ComboTree').combotree('enable');
            }

    后台负责直接把表数据,无脑的都一次性读出来就完事了。

    下面附上后台方法。

            #region 异步树
            [HttpPost]
            public JsonResult AsyncTree(int id = 0)
            {
                TOM.DAL.MenuRepository d = new TOM.DAL.MenuRepository();
                List<TOM.Model.TreeData> list = new List<TOM.Model.TreeData>();
                var query = d.List().Where(m => m.PID == id);
                foreach (var item in query)
                {
                    TOM.Model.TreeData temp = new TOM.Model.TreeData();
                    temp.id = item.ID.ToString();
                    temp.text = item.Text;
                    temp.state = hasChild(item.ID) ? "closed" : "open";
                    temp.iconCls = "icon-add";
                    temp.attributes = new TOM.Model.attribute() { url = item.URL };
                    list.Add(temp);
                }
                return Json(list);
            }
            /// <summary>
            /// 判断是否有子节点
            /// </summary>
            /// <param name="id">父节点ID</param>
            /// <returns>Bool</returns>
            private bool hasChild(int id)
            {
                TOM.DAL.MenuRepository d = new TOM.DAL.MenuRepository();
                var query = d.List().Where(m => m.PID == id);
                return query.Count() > 0;
            }
            #endregion
    
            #region 扩展支持{id=0,pid=0}格式的树
            [HttpPost]
            public JsonResult ExtTree()
            {
                TOM.DAL.MenuRepository d = new TOM.DAL.MenuRepository();
                List<TOM.Model.TreeData> list = new List<TOM.Model.TreeData>();
                var query = d.List();
                foreach (var item in query)
                {
                    TOM.Model.TreeData temp = new TOM.Model.TreeData();
                    temp.id = item.ID.ToString();
                    temp.pid = item.PID.ToString();
                    temp.text = item.Text;
                    temp.iconCls = "icon-add";
                    temp.attributes = new TOM.Model.attribute() { url = item.URL };
                    list.Add(temp);
                }
                return Json(list);
            }
            #endregion

    至于后台方法,看看就好了,本人MVC新手,写的不好。此文章也是我备忘用的。如果能给其他人带来方便那是最好的!

     最后附图全部效果

  • 相关阅读:
    Visual Studio 2019 Xamarin 设计器显示不正常
    Chrome 关闭稍后阅读/阅读清单功能
    Chrome 浏览器历史记录的日期格式转换 sqlite3
    将博客搬至CSDN
    python selenium 库利用 pytesseract 识别验证码方案
    layui OSS Web直传
    苹果App Store审核被拒记录(持续更新中...)
    iOS RSA加密解密
    PHP、Android、iOS接口RSA加密解密
    安卓RSA加密解密(简单复制直接使用)
  • 原文地址:https://www.cnblogs.com/tommyheng/p/3538667.html
Copyright © 2020-2023  润新知