• zTree初体验--MVC linq动态多条件OR查询


      工作需要,使用zTree实现了一个点击显示下拉复选框列表选中项作为查询条件的功能。简单记录下菜鸟级开发历程。

      zTree:是一个依靠jQuery实现的多功能树控件。通过简单引用配置就可使用。

      具体使用:

    (1)、脚本、样式引用

    注意:引用顺序,zTree.js一定放最后。

    <link rel="stylesheet" href="@Url.Content("~/Scripts/jquery.plugins/zTree/zTreeStyle.css")" type="text/css">
    <script src="@Url.Content("~/Scripts/jquery.plugins/zTree/jquery.ztree.core-3.5.js")"></script>
    <script src="@Url.Content("~/Scripts/jquery.plugins/zTree/jquery.ztree.excheck-3.5.js")"></script>
    <script src="@Url.Content("~/Scripts/jquery.plugins/jquery.json.js")"></script>
    <script src="@Url.Content("~/Scripts/jquery.plugins/zTree/zTree.js")"></script>

    (2)、前台展示

    说明:txt_InfoSource用来展示选中复选框后的数据,DashBoardCheckList为后台查询条件模型传递数据(怎么让txt_InfoSource为模型传递数据?!)。灰色背景为zTree控件展示。

    <div style="display:inline-block;">
            <div style="display:inline-block;">
                <input type="text" id="txt_InfoSource" class="width_130" readonly="readonly" value="@ViewBag.CheckList" />
                @Html.HiddenFor(MODEL => MODEL.DashBoardCheckList, new { @id = "DashBoardCheckList", @readonly = "readonly" })
            </div>
            <div id="menuContent" class="menuContent" style="display:none;z-index: 1000; position: absolute; background: #eee;">
                <ul id="tree" class="ztree" style=""></ul>
            </div>
        </div>

    (3)、操作脚本

       因为我实现了两个一样的功能,只是数据显示不一样,所以就写了两套zTree

    var functionManage = new FunctionManage();
    var zTree;
    $(document).ready(function ($) {
        functionManage.Init();
    });
    
    /// <summary>构造函数
    ///   <para></para>
    /// </summary>
    function FunctionManage() {
        //当前操作类型: 0= 默认值, 1= 添加新的, 2 = 更新
        this.CurOperType = 0;
        this.CurFunNode = null; //当前选择菜单节点对象
    }
    
    //**********public methods*************************
    /// <summary>初始化
    ///   <para>这是一个详细信息</para>
    /// </summary>
    /// <param name="_parameter" type="String">参数说明</param>
    /// <return></returen>
    FunctionManage.prototype.Init = function (_parameter) {
        this._BindEvent();
        this.LoadFunctionTree();
    }
    //**********private event methods******************
    
    /// <summary>绑定,注册点击事件
    ///  <para></para>
    /// </summary>
    FunctionManage.prototype._BindEvent = function () {
        var _this = this
        $("#txt_InfoSource").click(function () {
            $("#menuContent").show();
            $("body").bind("mousedown", _this.CaseStateOnBodyDown);
        });
    
        $("#txt_InfoSource2").click(function () {
            $("#menuContent2").show();
            $("body").bind("mousedown", _this.CaseStateOnBodyDown);
        });
    }
    
    /// <summary>加载功能树,在这里配置zTree的相关属性、事件,注意:回调事件名必须与官方一致,实现随意。
    /// <para></para>
    /// </summary>
    FunctionManage.prototype.LoadFunctionTree = function () {
        var setting = {
            check: {
                enable: true
            },
            view: {
                dblClickExpand: false,
                showLine: true,
                selectedMulti: false
            },
            data: {
                simpleData: {
                    enable: true,
                    idKey: "id",
                    pIdKey: "pId",
                    rootPId: ""
                }
            },
            callback: {
                onClick: functionManage.zTreeOnClick
                , onRightClick: functionManage.OnRightClick
                , onCheck: functionManage.zTreeOnClick
            }
        };
      
    
      //请求加载数据
        $.post("/TrackerGraph/GetModuleNameTreeList", { "ModuleName": $("#txt_InfoSource").val(), CoveredName: $("#txt_InfoSource2").val() }, function (data) {
            
        //我的返回数据类型是根据ModuleName和CoveredName返回 json+"="+json.
        //总感觉这么玩字符串略麻烦,不知有没有简单些的方式?!
         var array = new Array();
         //分割字符串
            array = data.split("=");
            var returnMsg = JSON.parse(array[0])
            if (returnMsg.Success) {
           //给树赋值
                $.fn.zTree.init($("#tree"), setting, JSON2.parse(returnMsg.Data));
                zTree = $.fn.zTree.getZTreeObj("tree");
            }
            else {
                alert(returnMsg.Message);
            }
            returnMsg = JSON.parse(array[1])
            
            if (returnMsg.Success) {
                $.fn.zTree.init($("#tree2"), setting, JSON2.parse(returnMsg.Data));
                zTree = $.fn.zTree.getZTreeObj("tree2");
            }
            else {
                alert(returnMsg.Message);
            }
        });
    }
    
    /// <summary>复选框选择事件
    ///   <para></para>
    /// </summary>
    FunctionManage.prototype.zTreeOnClick = function (e, treeId, treeNode) {
        var zTree = $.fn.zTree.getZTreeObj(treeId),
        nodes = zTree.getCheckedNodes(true),
        vName = "";
        var statusValue = "", solStatusValue = ""; //主表状态,处理状态值。
        for (var i = 0, l = nodes.length; i < l; i++) {
            if (nodes[i].isParent == false) {
           //每个节点都有nsme跟value,用起来很方便
                statusValue += nodes[i].value + ",";
                vName += nodes[i].name + ",";
            }
        }
    
        vName = vName.substr(0, vName.length - 1);
      //选择节点后,更新前台数据
        if (treeId == "tree") {
            $("#txt_InfoSource").val(vName.toString());
            $("#DashBoardCheckList").val(vName.toString());
        }
        if (treeId == "tree2") {
            $("#txt_InfoSource2").val(vName.toString());
            $("#CoveredModelCheckList").val(vName.toString());
        }
    
    }
    
    /// <summary>显示树
    ///   <para>控件ID</para>
    /// </summary>
    FunctionManage.prototype.showMenu = function (controlID) {
        var cityObj = $("#" + controlID);
        var cityOffset = $("#" + controlID).offset();
        if (controlID == "aInfoSource") {
            //cityOffset.top + cityObj.outerHeight()
            $("#menuContent").css({ left: cityOffset.left + "px", top: 60 + "px" }).slideDown("fast");
            $("body").bind("mousedown", this.CaseStateOnBodyDown);
        }
        if (controlID == "menuStreet") {
            $("#divStreet").css({ left: cityOffset.left + "px", top: cityOffset.top + cityObj.outerHeight() + "px" }).slideDown("fast");
            $("body").bind("mousedown", this.StreetOnBodyDown);
        }
    
        if (controlID == "aInfoSource2") {
            $("#menuContent2").css({ left: cityOffset.left + "px", top: 60 + "px" }).slideDown("fast");
            $("body").bind("mousedown", this.CaseStateOnBodyDown);
        }
        if (controlID == "menuStreet2") {
            $("#divStreet").css({ left: cityOffset.left + "px", top: cityOffset.top + cityObj.outerHeight() + "px" }).slideDown("fast");
            $("body").bind("mousedown", this.StreetOnBodyDown);
        }
    
    }
    
    /// <summary>隐藏Module Name树列表
    ///   <para></para>
    /// </summary>
    FunctionManage.prototype.CaseStateHideMenu = function () {
        $("#menuContent").fadeOut("fast");
        $("#menuContent2").fadeOut("fast");
        $("body").unbind("mousedown", this.CaseStateOnBodyDown);
    }
    
    FunctionManage.prototype.CaseStateOnBodyDown = function (event) {
        if (!(event.target.id == "txt_InfoSource" ||
             event.target.id == "menuContent" ||
            $(event.target).parents("#menuContent").length > 0 ||
            event.target.id == "txt_InfoSource2" ||
             event.target.id == "menuContent2" ||
            $(event.target).parents("#menuContent2").length > 0
         )) {
            functionManage.CaseStateHideMenu();
        }
    }
    View Code

    引用了上面脚本之后,就成功一半了,剩下的就是后台数据处理了。

    (4)、客户端加载数据

    a.页面初次加载,直接从数据库读取数据展示出来。否则根据查询条件,显示数据。

    b.zTree数据加载

     /// <summary>
            ///  获取zTree节点列表
            /// </summary>
            /// <returns></returns>
            public string GetModuleNameTreeList(string ModuleName, string CoveredName)
            {
                //1)定义根节点对象
                JsonTreeItem rootNode = new JsonTreeItem();
                JsonTreeItem CoveredrootNode = new JsonTreeItem();
                rootNode.id = "0";
                rootNode.pId = "0";
                rootNode.name = "ModuleName";
                rootNode.children = new List<JsonTreeItem>();
                rootNode.open = "true";
                rootNode.IsChecked = !string.IsNullOrEmpty(ModuleName);
    
                CoveredrootNode.id = "0";
                CoveredrootNode.pId = "0";
                CoveredrootNode.name = "CoveredModuleName";
                CoveredrootNode.children = new List<JsonTreeItem>();
                CoveredrootNode.open = "true";
                CoveredrootNode.IsChecked = !string.IsNullOrEmpty(CoveredName);
    
                //2)缓存所有菜单节点数据
                var list = (from raw in db.TR_Words
                            where raw.WordType == 11 && raw.ModuleName == "TR"
                            select new { raw.WordName, raw.WordValue });
                //3)遍历加载一级根节点
                if (list != null)
                {
                    foreach (var item in list)
                    {
                        bool isChecked = false;
                        if (ModuleName != null && ModuleName.IndexOf(item.WordName) != -1)
                        {
                            isChecked = true;
                        }
                        //定义一级节点,参数参考JsonTreeItem模型中的说明
                        JsonTreeItem LevelNode1 = new JsonTreeItem("0", rootNode.id, item.WordName, item.WordName.ToString(), "", isChecked, false, "false");
                        //根节点添加一级节点
                        rootNode.children.Add(LevelNode1);
    
                        bool CoveredisChecked = false;
                        if (CoveredName != null && CoveredName.IndexOf(item.WordName) != -1)
                        {
                            CoveredisChecked = true;
                        }
                        //定义一级节点
                        JsonTreeItem CoveredLevelNode1 = new JsonTreeItem("0", CoveredrootNode.id, item.WordName, item.WordName.ToString(), "", CoveredisChecked, false, "false");
                        //根节点添加一级节点
                        CoveredrootNode.children.Add(CoveredLevelNode1);
                    }
                }
                string returnJsonValue = GetJson(rootNode);
                string returnCoveredJsonValue = GetJson(CoveredrootNode);
                return returnJsonValue + "=" + returnCoveredJsonValue;
            }    
    View Code

    JsonTreeItem模型:

    namespace Opentide.DataContracts
    {
        /// <summary>Json树对象结构
        /// 
        /// </summary>
        [DataContractAttribute]
        [Serializable]
        public class JsonTreeItem 
        {
            /// <summary>
            /// treeNode 节点的唯一标识 tId。
            /// </summary>
            [DataMember]
            public string  id { get; set; }
    
            ///<summary>
            /// 节点名称
            ///</summary>
            [DataMember]
            public string name { get; set; }
    
            ///<summary>
            /// 节点值
            ///</summary>
            [DataMember]
            public string value { get; set; }
    
            ///<summary>
            /// 父节点id
            ///</summary>
            [DataMember]
            public string pId { get; set; }
    
    
            ///<summary>
            /// 节点层级
            ///</summary>
            [DataMember]
            public string level { get; set; }
    
            ///<summary>
            /// 节点的子节点数据集合
            ///</summary>
            [DataMember]
            public List<JsonTreeItem> children { get; set; }
    
            /// <summary>
            /// 记录 treeNode 节点的 展开 / 折叠 状态。
            /// </summary>
            [DataMember]
            public string open  { get; set; }
    
            ///<summary>
            /// 节点自定义图标的 URL 路径
            ///</summary>
            [DataMember]
            public string icon { get; set; }
    
            ///<summary>
            /// 节点链接的目标 URL
            ///</summary>
            [DataMember]
            public string url { get; set; }
    
    
            ///<summary>
            /// 节点链接的目标 URL2
            ///</summary>
            [DataMember]
            public string url2 { get; set; }
    
    
            ///<summary>
            /// 是否选中复选框
            ///</summary>
            [DataMember]
            public bool nocheck { get; set; }
    
            ///<summary>
            /// 是否选中复选框
            ///</summary>
            [DataMember(Name="checked")]
            public bool IsChecked { get; set; }
    
            ///<summary>
            /// 当前登录用户ID
            ///</summary>
            [DataMember]
            public string UserID { get; set; }
    
    
            ///<summary>
            /// 菜单排序ID
            ///</summary>
            [DataMember]
            public int SortID { get; set; }
    
    
            ///<summary>
            /// 菜单状态0-不禁用,1-正常
            ///</summary>
            [DataMember]
            public int Status { get; set; }
    
    
    
            public JsonTreeItem()
            {
     
            }
    
    
            /// <summary>构造节点实例信息
            /// 
            /// </summary>
            /// <param name="id">节点ID</param>
            /// <param name="pid">父节点</param>
            /// <param name="name">节点名称</param>
            /// <param name="_value">节点值</param>
            /// <param name="url">url地址</param>
            /// <param name="_isChecked">是否选中复选框</param>
            public JsonTreeItem(string _id, string _pid, string _name, string _value, string _url, bool _isChecked)
            {
                this.id = _id;
                this.pId = _pid;
                this.name = _name;
                this.value = _value;
                this.url = _url;
                this.IsChecked = _isChecked;
            }
    
            /// <summary>构造节点实例信息
            /// 
            /// </summary>
            /// <param name="id">节点ID</param>
            /// <param name="pid">父节点</param>
            /// <param name="name">节点名称</param>
            /// <param name="_value">节点值</param>
            /// <param name="_url">url地址</param>
            /// <param name="_isChecked">是否选中复选框</param>
            /// <param name="_nocheck">是否隐藏复选框</param>
            /// <param name="_nocheck">是否打开子节点</param>
            public JsonTreeItem(string _id, string _pid, string _name, string _value,string _url, bool _isChecked, bool _nocheck,string _open)
            {
                this.id = _id;
                this.pId = _pid;
                this.name = _name;
                this.value = _value;
                this.IsChecked = _isChecked;
                this.nocheck = _nocheck;
                this.open = _open;
            }
        }
    }
    View Code

    值得一提的是,在使用linq做动态多条件OR查询的时候使用了Expressions扩展:PredicateExtensions。

    namespace Opentide.Common.Extension
    {
        /// <summary>
        /// 构造函数使用True时:单个AND有效,多个AND有效;单个OR无效,多个OR无效;混合时写在AND后的OR有效
        /// 构造函数使用False时:单个AND无效,多个AND无效;单个OR有效,多个OR有效;混合时写在OR后面的AND有效
        /// </summary>
        public static class PredicateExtensions
        {
            public static Expression<Func<T, bool>> True<T>() { return f => true; }
            public static Expression<Func<T, bool>> False<T>() { return f => false; }
            public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expression1, Expression<Func<T, bool>> expression2)
            {
                var invokedExpression = Expression.Invoke(expression2, expression1.Parameters.Cast<Expression>());
                return Expression.Lambda<Func<T, bool>>(Expression.Or(expression1.Body, invokedExpression), expression1.Parameters);
            }
            public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expression1, Expression<Func<T, bool>> expression2)
            {
                var invokedExpression = Expression.Invoke(expression2, expression1.Parameters.Cast<Expression>());
                return Expression.Lambda<Func<T, bool>>(Expression.And(expression1.Body, invokedExpression), expression1.Parameters);
            }
        }
    }
    
    private List<TR_TrackerRaw> GetCoveredModelNameBaseList(TrackerGraphSearch search, List<TR_TrackerRaw> list)
            {
                if (search.CoveredModelCheckList != null)
                {
                    string CoveredModelCheckList = search.CoveredModelCheckList.ToString();
    
                    string[] CoveredArray = CoveredModelCheckList.Split(',');
    
                    list = GetNeedReceive(list, CoveredArray);
                }
                return list;
            }
    
            private static List<TR_TrackerRaw> GetNeedReceive(List<TR_TrackerRaw> list, Array hubID)
            {
                IQueryable<TR_TrackerRaw> useList = list.AsQueryable();
                try
                {
                    var predicate = PredicateExtensions.False<TR_TrackerRaw>();
                    foreach (string h in hubID)
                    {
                        string htemp = h;
                        predicate = predicate.Or(c => c.ModuleName == htemp);
                    }
                    return useList.Where(predicate).ToList();
                }
                catch (Exception ex)
                {
                    //_log.Error(ex.ToString());
                    return null;
                }
            }
    View Code

    还有很多不足,欢迎大神不吝指教。

    最后附上参考博文:

    zTree官网:http://www.ztree.me/v3/main.php#_zTreeInfo

    linq动态查询:

    http://weblogs.asp.net/scottgu/dynamic-linq-part-1-using-the-linq-dynamic-query-library

    http://www.cnblogs.com/killuakun/archive/2008/08/03/1259389.html

  • 相关阅读:
    N-Queens
    Pow(x, n)
    Maximum Subarray
    Spiral Matrix
    Jump Game
    Merge Intervals
    Insert Interval
    Length of Last Word
    Spiral Matrix II
    Amazon 面经
  • 原文地址:https://www.cnblogs.com/FlyBKB/p/5052852.html
Copyright © 2020-2023  润新知