无限级分类Asp.net Mvc实现

无限级分类Asp.net Mvc实现
 
无限级分类涉及到异步加载子类、加载当前类和匹配问题,现在做一个通用的实现。
 
(一) 效果如下:
 
(二)设计、实现及使用
(1)数据库
(a)表设计dbo.Categories
列名
类型
说明
CategoryId
int
主键,增量为1的标识符
Name
nvarchar(50) 分类名称
ParentId
int
父类Id
Path
nvarchar(100)
分类路径,用以表示该类的层级关系
CreatedAt
datetime
创建时间
(b)测试数据

(2)前台设计
(a)分部视图-加载一个子类:_LoadCategory.cshtml
@using RspTest.Models;
@model int
@{
    Layout = null;
    var context = new MvcTestEntities();
    var subCats = new List<Category>();
    subCats = context.Categories.Where(x => x.ParentId == Model || Model == 0 && x.ParentId == null).ToList();
    var selectedCid = (int)ViewBag.selectedCid;
    }
@if(subCats.Count>0)
{
<select name="category" class="category">
    <option value="">请选择</option>
    @foreach (var sub in subCats)
    {
        <option value="@sub.CategoryId" @(sub.CategoryId == selectedCid?"selected":"")>@sub.Name</option>
    }
</select>
}
(b)分部视图-加类某个类:_LoadCategories.cshtml
@using RspTest.Models
@model int
@{
    Layout = null;
    var context = new MvcTestEntities();
    var currentCat = context.Categories.Find(Model);
    var cids = new List<int>{0};
    if(currentCat!=null)
    {
        if(!string.IsNullOrEmpty(currentCat.Path))
        {
            var paths = currentCat.Path.Split(',');
            int tmpCatId = 0;
            for(var i=0;i<paths.Length;i++)
            {
                var catIdStr = paths[i];
                if (int.TryParse(catIdStr, out tmpCatId))
                {
                    cids.Add(tmpCatId);
                }
            }
        }
    }
    cids.Add(0);//作为当前分类的子分类的默认选中值
    }
<div class="categories-wrap">
    @for (var i=0;i<cids.Count-1;i++)
    {
        var cid = cids[i];
        ViewBag.selectedCid = cids[i+1];
        @Html.Partial("_LoadCategory",cid)
    }
</div>
(c)视图-使用无限级分类进行查找:Index.cshtml
@using RspTest.Models
@model List<Category>
@{
    ViewBag.Title = "分类列表";
}
<h2>分类列表</h2>
<script src="~/Scripts/jquery-1.7.1.js"></script>
<style type="text/css">
    .category {
        margin-right:10px;
    }
    th,td {
        border:1px solid black;text-align:center;
    }
    tr {
        text-align:center;
    }
    fieldset {
        border:1px solid black;margin-top:10px;
    }
    form > ul > li {
        float:left;margin-right:15px;
        list-style-type:none;
    }
</style>
<fieldset>
    <legend>搜索</legend>
    <form action="/categories" method="get">
        <ul>
            <li>类别:</li>
            <li>
    @Html.Partial("_LoadCategories",(int)ViewBag.cid)
                </li>
            <li>
        <input type="submit" value="搜索" />
                </li>
            </ul>
    </form>
</fieldset>
<table>
    <thead>
        <tr>
            <th>编号</th>
            <th>名称</th>
            <th>父类</th>
            <th>路径</th>
        </tr>
    </thead>
    <tbody>
        @foreach(var cat in Model)
        {
            <tr>
                <td>
                    @cat.CategoryId
                </td>
                <td>
                    @cat.Name
                </td>
                <td>
                    @cat.ParentId
                </td>
                <td>
                    @cat.Path
                </td>
            </tr>
        }
    </tbody>
</table>
<script type="text/javascript">
    $(document).ready(function () {
        $(".category").live("change", function (e) {
            var $current = $(this);
            if ($current.val() == "") {
                $current.nextAll(".category").remove();
                return false;
            }
            $.ajax({
                url: "/categories/getsubcategories/" + $current.val(),
                type: "post",
                success: function (data, text) {
                    //alert(data);
                    //先清除所以子分类
                    $current.nextAll(".category").remove();
                    var $eles = $(data);
                    if ($eles.find("option").length > 1) {//除去“请选择”之外,还有选项的情况才加载子类
                        $eles.insertAfter($current);
                    }
                    else {
                    }
                }
            })
        });
    });
</script>
 
(3)后台代码
(a)Action-异步获取子类:GetSubCategories
public ActionResult GetSubCategories(int id)
        {
            ViewBag.selectedCid = 0;
            return View("_LoadCategory", id);
        }
(b)Action-分类列表:Index
public ActionResult Index()
        {
            int cid = 0;
            if (!string.IsNullOrEmpty(Request.Params["category"]))
            {
                //一般会按name将元素的值用“,”连接起来,因此,需要取该参数的最后一个合法值
                var cidsStr = Request.Params["category"].Trim();
                foreach (var cidStr in cidsStr.Split(','))
                {
                    var tmpCid = 0;
                    if (int.TryParse(cidStr, out tmpCid))
                    {
                        cid = tmpCid;
                    }
                }
            }
            var category = context.Categories.Find(cid);
            var pathSearch = ","+cid+",";
            ViewBag.cid = cid;
            var categories = context.Categories.Where(x => x.Path.Contains(pathSearch) || cid == 0).ToList();
            return View(categories);
        }
 
说明:一个页面,可加载多个分类。
 
文章系本人原创,欢迎转载,转载时请注明出处。
原文地址:https://www.cnblogs.com/xiaxiazl/p/3440169.html