zoukankan      html  css  js  c++  java
  • MVC树控件,mvc中应用treeview,实现复选框树的多层级表单控件

    类似于多层级的角色与权限控制功能,用MVC实现MVC树控件,mvc中应用treeview,实现复选框树的多层级表单控件。最近我们的项目中需要用到树型菜单,以前使用WebForm时,树型菜单有微软提供的控件,非常方便,但现在需要在asp.netmvc中使用树形菜单,先说明下我们对树形菜单的需求:

    1,支持CheckBox,允许对菜单项进行选择;
    2,当选择父菜单时,它下面的子菜单全部选中;
    3,当取消父菜单的选中状态时,下面的子菜单也全部取消;
    4,比较方便的与MVC结合;

    5,能够初始化选中状态。

    6,能够以提交表单的方式,一次性将树绑定到后台接收的对象。

    首先菜单数据对象:

    完整的 CheckboxTreeHelper.cs 代码:

      1 using System;
      2 using System.Collections.Generic;
      3 using System.Linq;
      4 using System.Web;
      5 using System.Web.Mvc;
      6 using System.Web.Mvc.Html;
      7 using System.Text;
      8 
      9 /*
     10 author:熊学浩
     11 time:2016年6月5日
     12 description:树形菜单控件(有问题请致信:xiongzaiqiren@163.com),或者请参考【http://www.cnblogs.com/xiongzaiqiren/ 13 */
     14 namespace System.Web.Mvc
     15 {
     16     /// <summary>
     17     /// 菜单数据对象
     18     /// </summary>
     19     public class CheckboxTreeItem
     20     {
     21         /// <summary>
     22         /// 显示的文本
     23         /// </summary>
     24         public string Text { get; set; }
     25         /// <summary>
     26         /// 显示文本对应的值
     27         /// </summary>
     28         public string Value { get; set; }
     29         /// <summary>
     30         /// 是否被选中
     31         /// </summary>
     32         public bool Checked { get; set; }
     33         /// <summary>
     34         /// 结合表单的辅助属性,View上使用(注意每个层级的索引必需从0开始并且是连续的)
     35         /// </summary>
     36         public string Index { get; set; }
     37 
     38         /// <summary>
     39         /// 子菜单集合
     40         /// </summary>
     41         public IList<CheckboxTreeItem> Items { get; set; }
     42     }
     43 
     44     /// <summary>
     45     /// 复选框树控件
     46     /// 熊学浩
     47     /// 2016年6月3日
     48     /// </summary>
     49     public static class CheckboxTreeHelper
     50     {
     51         private static bool baselayer;
     52 
     53         public static String CheckboxTree(this HtmlHelper helper, string Name, CheckboxTreeItem Model, out string this_HtmlDomName, bool isChildNode = false)
     54         {
     55             if (null == Model)
     56             {
     57                 this_HtmlDomName = string.Empty;
     58                 return string.Empty;
     59             }
     60 
     61             StringBuilder sb = new StringBuilder();
     62             if (!baselayer)
     63                 sb.Append("<div class="CheckboxTree">");
     64 
     65             if (!isChildNode)
     66                 sb.Append("<ul class="CBT-ul">");
     67             sb.Append("<li class="CBT-li">");
     68 
     69             this_HtmlDomName = Name + "[" + Model.Index + "]";
     70 
     71             sb.Append("<label style="cursor:pointer;">");
     72             sb.AppendFormat("<input type="checkbox" onchange="setCheckboxTreeItemValue(this);" name="{0}" value="{1}" />", (this_HtmlDomName + ".Checked"), Model.Checked.ToString());
     73             sb.AppendFormat("<span>{0}</span>", Model.Text);
     74             sb.Append("</label>");
     75 
     76             sb.AppendFormat("<input type="hidden" name ="{0}" value="{1}" />", (this_HtmlDomName + ".Text"), Model.Text);
     77             sb.AppendFormat("<input type="hidden" name ="{0}" value="{1}" />", (this_HtmlDomName + ".Value"), Model.Value);
     78             sb.AppendFormat("<input type="hidden" name ="{0}" value="{1}" />", (this_HtmlDomName + ".Index"), Model.Index);
     79 
     80             if (null != Model.Items)
     81             {
     82                 sb.Append("<ul class="CBT-ul">");
     83                 for (var i = 0; i < Model.Items.Count; i++)
     84                 {
     85                     string _this_HtmlDomName;
     86                     sb.Append(CheckboxTree(helper, this_HtmlDomName + ".Items", Model.Items[i], out _this_HtmlDomName, true));
     87                 }
     88                 sb.Append("</ul>");
     89             }
     90 
     91             sb.Append("</li>");
     92             if (!isChildNode)
     93                 sb.Append("</ul>");
     94 
     95             if (!baselayer)
     96                 sb.Append("</div>");
     97 
     98             return sb.ToString();
     99         }
    100         public static String CheckboxTree(this HtmlHelper helper, string Name, IList<CheckboxTreeItem> Models)
    101         {
    102             if (null == Models) return string.Empty;
    103             if (Models.Count > 0)
    104                 baselayer = true;
    105 
    106             StringBuilder sb = new StringBuilder();
    107             if (baselayer)
    108                 sb.Append("<div class="CheckboxTree">");
    109             sb.Append("<ul class="CBT-ul">");
    110 
    111             string _this_HtmlDomName;
    112 
    113             foreach (CheckboxTreeItem item in Models)
    114             {
    115                 sb.Append(CheckboxTree(helper, Name, item, out _this_HtmlDomName, true));
    116             }
    117 
    118             sb.Append("</ul>");
    119             if (baselayer)
    120                 sb.Append("</div>");
    121 
    122             return sb.ToString();
    123         }
    124     }
    125 }

    字段说明:
    Text:用于显示的文本,比如:总裁
    Value:显示文本对应的ID,比如:0
    Index:这个是结合表单的辅助属性,View上使用(注意每个层级的索引必需从0开始并且是连续的)
    Checked:当前菜单项是否被选中,用户提交表单后我们可以通过这个属性判断用户的选择项
    Items:当前菜单下的子菜单集合

    树形菜单的输出:

     1 @model List<CheckboxTreeItem>
     2 
     3 
     4 @using (Html.BeginForm("test", "Home", new { }, FormMethod.Post, new { id = "form", name = "form" }))
     5 {
     6   @Html.AntiForgeryToken();
     7     
     8   <link type="text/css" rel="stylesheet" href="@Url.Content("~/Models/CheckboxTree.css")" />
     9   @Html.Raw(Html.CheckboxTree("CheckboxTree", Model))   @*这里是输出显示树形菜单*@
    10   <script src="@Url.Content("~/Models/CheckboxTree.js")" type="text/javascript"></script>
    11 }

           无论是ajax还是直接post表单,最终的目的都是接收View中的数据,要想传递比较复杂的数据类型,我们需要对ASP.NET MVC Model Binding 有一定了解,之前也讲解过MyTreeViewItem的结果,有普通的数据类型,比如 string,bool,也是对象类型,比如MyTreeViewItem类型的Parent,也是基于集合的属性IList<MyTreeViewItem>,要想让表单中的数据直接传递给Controller,我们需要对表单元素的name进行特殊处理才行。

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

     1 public ActionResult test(int id = 0)
     2 {
     3     ViewBag.IsEdit = id == 0 ? false : true;
     4 
     5     List<CheckboxTreeItem> cb = new List<CheckboxTreeItem>() {
     6             new CheckboxTreeItem() { Value="A", Text="一级A", Index="0" },
     7             new CheckboxTreeItem() { Value="B", Text="一级B", Index="1" },
     8             new CheckboxTreeItem() { Value="C", Text="一级C", Index="2", Checked =true,
     9             Items=new List<CheckboxTreeItem>() {
    10                 new CheckboxTreeItem() { Value="CA", Text="二级CA", Index="0", Checked =true },
    11                 new CheckboxTreeItem() { Value="CB", Text="二级CB", Index="1", Checked =true,
    12                 Items=new List<CheckboxTreeItem>() {
    13                     new CheckboxTreeItem() { Value="CBA", Text="三级CBA", Index="0", Checked =true },
    14                     new CheckboxTreeItem() { Value="CBB", Text="三级CBB", Index="1", Checked =true },
    15                     }
    16                 },
    17             }
    18             },
    19     };
    20 
    21     return View(cb);
    22 }
    23 
    24 [HttpPost]
    25 [ValidateAntiForgeryToken]
    26 [ValidateInput(false)]
    27 public ActionResult test(List<CheckboxTreeItem> CheckboxTree, int id = 0)
    28 {
    29     ViewBag.IsEdit = id == 0 ? false : true;
    30 
    31     return View(CheckboxTree);
    32 }

    下图是Controller接收到的参数:(运行调试,断点查看第27-31行代码)

    另外还有自定义样式文件 CheckboxTree.css

     1 /*
     2 author:熊学浩
     3 time:2016年6月5日
     4 description:树形菜单控件(有问题请致信:xiongzaiqiren@163.com),或者请参考【http://www.cnblogs.com/xiongzaiqiren/ 5 */
     6 /* CheckboxTree */
     7 .CheckboxTree {
     8      100%;
     9     height: 100%;
    10     text-align: center;
    11     margin: 0 auto;
    12 }
    13 
    14 .CBT-ul {
    15     text-align: left;
    16     list-style-type: disc;
    17 }
    18 
    19     .CBT-ul .CBT-li {
    20         display: list-item;
    21         text-align: left;
    22         margin-left: 10px;
    23         font-size: 16px;
    24         line-height: 20px;
    25         word-wrap: break-word;
    26         word-break: nomal;
    27         list-style: inherit;
    28     }
    29 .CBT-li label {
    30     cursor: pointer;
    31 }
    32 .CBT-li label input[type="checkbox"] {
    33      16px;
    34     height: 16px;
    35     padding: 0 5px 0 0;
    36 }
    37 
    38 .CBT-li span {
    39     
    40 }
    41 
    42     .CBT-li a:link, .CBT-li a:visited {
    43     }
    44 
    45     .CBT-li a:hover, .CBT-li a:active {
    46         color: #ffffff;
    47         background-color: #657386;
    48     }
    49 
    50     .CBT-li a.active {
    51         color: #ffffff;
    52         background-color: #657386;
    53     }
    54 
    55     .CBT-li a span {
    56         
    57     }
    CheckboxTree.css

    用于初始化和设置选择状态改变的自定义javascript文件 CheckboxTree.js

     1 /*
     2 author:熊学浩
     3 time:2016年6月5日
     4 description:树形菜单控件(有问题请致信:xiongzaiqiren@163.com),或者请参考【http://www.cnblogs.com/xiongzaiqiren/ 5 */
     6 /* CheckboxTree */
     7 function setCheckboxTreeItemValue(dom) {
     8     try {
     9         if (!!dom)
    10             dom.value = (!!dom.checked)
    11     }
    12     catch (e) {
    13         console.log(e.message);
    14     }
    15 };
    16 function iniCheckboxTree() {
    17     try {
    18         var cbList = document.getElementsByTagName("input");
    19         if (!!cbList && cbList.length > 0) {
    20             for (var i = 0; i < cbList.length; i++) {
    21                 if (!!cbList[i] && (cbList[i].type == "checkbox")) {
    22                     if (!!cbList[i].value) {
    23                         cbList[i].checked = (cbList[i].value.toLowerCase() == "true") || false;
    24                     }
    25                 }
    26             }
    27         }
    28     }
    29     catch (e) {
    30         console.log(e.message);
    31     }
    32 };
    33 
    34 if (!!window)
    35     window.onload = iniCheckboxTree();
    36 else
    37     iniCheckboxTree();
    CheckboxTree.js

    最后,UI效果图:

    【完】

  • 相关阅读:
    chrome 浏览器与chromedriver 对应关系以及 对应的驱动下载
    pip 安装six 报错 ModuleNotFoundError: No module named 'pip._internal.cli.main'
    django 连接远程mysql 报错 django.db.utils.OperationalError: (1045, "Access denied for user 'root'@'localhost' (using password: NO)")
    MySQL8.0允许外部访问
    Linux 安装mysql
    php导出导入excel插件
    解决php导出csv文件utf8中文乱码问题
    Docker 安装mysql5.6
    centos7 设置静态IP
    U盘制作centos7系统并安装
  • 原文地址:https://www.cnblogs.com/xiongzaiqiren/p/CheckboxTree.html
Copyright © 2011-2022 走看看