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();
    }
}

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

(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;
        }    

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;
        }
    }
}

值得一提的是,在使用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;
            }
        }

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

最后附上参考博文:

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

时间: 2025-01-15 19:38:46

zTree初体验--MVC linq动态多条件OR查询的相关文章

zTree初体验(一)——小试牛刀

zTree 是一个依靠 jQuery 实现的多功能 "树插件".优异的性能.灵活的配置.多种功能的组合是 zTree 最大长处. --zTree官网 zTree v3.0 将核心代码依照功能进行了切割,不须要的代码能够不用载入 採用了 延迟载入 技术,上万节点轻松载入,即使在 IE6 下也能基本做到秒杀 兼容 IE.FireFox.Chrome.Opera.Safari 等浏览器 支持 JSON 数据 支持静态 和 Ajax 异步载入节点数据 支持随意更换皮肤 / 自己定义图标(依靠c

zTree初体验(二)——再续前缘

上篇文章简介了下zTree,以及简单实现.本篇书接上文,进行一下扩展,来看一下怎么从后台获取简单格式Json数据. 1). 我们就以项目中的部门组织结构为例,先从Manager层的方法开始.为了便于转Json,采用的是map形式的hql语句,这样出来的数据,是标准的key-value形式. /** * map的形式加载所有的部门 * @return List<DepTree> * 部门的List集合 * @author 张连海 * @since 2015.07.10 */ @SuppressW

linq 动态组合条件

http://www.albahari.com/nutshell/predicatebuilder.aspx Dynamically Composing Expression Predicates Suppose you want to write a LINQ to SQL or Entity Framework query that implements a keyword-style search. In other words, a query that returns rows who

Silverlight学习(四) domainservice动态多条件查询

上次讲了silverlight+MVVN+EF的简单框架,能够实现简单的数据CURD,但是多条件动态的查询一直没有实现.在网上查阅了很多资料,发现自己走了很多误区,代码很难调试正确. 这次的查询是基于上次的查询,只是增加了一个查询条件,动态多条件的查询的重点是获取查询的语言. 1 private string GetSql() 2 { 3 string query = "1=1"; 4 if (!string.IsNullOrEmpty(searchText.name)) 5 { 6

LINQ to Object初体验(使用对象取代二维数组作数据筛选)

VS2008里面有个神奇的东西,称之为LINQ,可以透过相同的语法方式来处理各式各样的数据(SQL,XML,Object,...),小喵此次初体验感受一下这个东西,真的很好用,初体验来做个简单的测试,请看小喵娓娓道来 VS2008里面有个神奇的东西,称之为LINQ,可以透过相同的语法方式来处理各式各样的数据(SQL,XML,Object,...),小喵此次初体验感受一下这个东西,真的很好用,初体验来做个简单的测试,请看小喵娓娓道来 先来看一张LINQ的架构图(数据来源:曹祖圣老师在TechEd2

ASP.NET MVC学习---(五)MVC初体验

经过之前n多的铺垫 我们已经大概了解了这个姓m名vc的家伙了 那么今天我们就来体验一把 怎么体验呢? 就来做一个小例子吧~ mvc增删改查的例子 数据库还是之前我们的老朋友 关系图: 表中的数据已填好 T_Users 将就着用着吧,哈哈 现在要求对T_Users表进行增删改查 开搞~ 回到之前新建的mvc项目 在Controllers文件夹下新建一个名为Home的空控制器 当浏览器请求Home下面的Index方法的时候返回什么? 当然是主页面啦 这里我们的主页面就是显示T_Users数据列表 代

LinQ从零开始---初体验

LinQ从零开始---初体验 LinQ是什么? LINQ,语言集成查询(LanguageIntegrated Query)是一组用于c#和Visual Basic语言的扩展.它允许编写C#或者Visual Basic代码以查询数据库相同的方式操作内存数据. LinQ要解决什么问题? 面向对象与数据访问两个领域长期分裂,各自为政, 编程语言中的数据类型与数据库中的数据类型形成两套体系. C# 中字符串用 string 表示 SQL 中字符串用 NVarchar/Varchar/Char 表示 SQ

SSH初体验系列--Hibetnate--2--crud操作

Ok,今天比较详细的学习一下hibernate的C(create).R(read).U(update).D(delete) 相关api... 前言 Session: 是Hibernate持久化操作的基础,提供了众多的数据库操作方法,如save(),update(),delete()...etc,用于完成对象的增加,修改,删除等方法. 后面代码中使用到的HinernateUtil类:是用于构建SessionFactory(Hibernate提供的获取session的工厂类)的一个封装类,在前面的文

ArcGis SOE(server object extensions)之REST Template初体验

一.安装vs和arcgis server for .net(本例是vs2010.as 10),然后打开vs新建一个项目 二.项目创建成功后(本例项目名称是GetArea),打开.cs文件. 三.接口方法说明 private RestResource CreateRestSchema() { RestResource rootRes = new RestResource(soe_name, false, RootResHandler); RestOperation sampleOper = new