ASP.NET?MVC實現城市或車型三級聯(lián)動
三級或多級聯(lián)動的場景經常會碰到,比如省、市、區(qū),比如品牌、車系、車型,比如類別的多級聯(lián)動......我們首先想到的是用三個select來展示,這是最通常的做法。但在另外一些場景中,比如確定搜索條件的時候,對于三級聯(lián)動來說,可能選擇1個,2個,或3個條件,我想,以下的方式可能更適合:

以上,可以只選擇品牌,或同時選擇品牌、車系,或同時選擇品牌、車系、車型,最后把選擇的內容展示到input上,并以逗號隔開。

可以實現的功能包括:
- 點擊最上面的input彈出div,此時只顯示品牌區(qū)域
- 點擊最左邊拼音首字母,導航到對應的品牌上
- 當把鼠標移動到某個品牌上,品牌為選中狀態(tài),其對應的車系顯示在車系區(qū)域
- 當鼠標不在任何品牌上,所有品牌都為不選中狀態(tài)
- 當把鼠標移動到某個車系上,車系為選中狀態(tài),其對應的車型顯示在車型區(qū)域,選中車系的所屬品牌也為選中狀態(tài)
- 當鼠標不在任何車系上,所有車系、品牌都為不選中狀態(tài)
- 當把鼠標移動到某個車型上,車型為選中狀態(tài),選中車型的所屬車系為選中狀態(tài),選中車系所屬品牌為選中狀態(tài)
- 當鼠標不在任何車型上,所有車型、車系、品牌為不選中狀態(tài)
- 點擊品牌,品牌顯示到input上
- 點擊車系,品牌、車系顯示到input上,并以逗號隔開
- 點擊車型,品牌、車系、車型顯示到input上,并以逗號隔開
- 點擊div上的關閉按鈕或者頁面空白區(qū)域,div隱藏
界面的構成如下:

- 最上面的是一個input
- 品牌、車系、車型被包裹在一個div中,點擊關閉按鈕或點擊空白處關閉的就是這個div
- 品牌區(qū)域是一個div,分為首字母導航div和品牌顯示div
- 車系區(qū)域是一個div
- 車型區(qū)域是一個div
- 品牌、車系、車型內的內容是一些dl, dt, dd的html元素
- 樣式的事情交給css
實現的思路大致這樣:
- 給input點擊事件,點擊彈出品牌、車系、車型顯示的div,并綁定頁面空白區(qū)域的點擊事件
- 導航首字母指向錨點,品牌按首字母分類并提供錨點id
- 在控制器中把品牌按照首字母分類,以json格式返回到前端,填充到tmpl模版,再追加到頁面品牌區(qū)域
- 給品牌添加鼠標移上事件,品牌為選中狀態(tài),對應的車系顯示在車系區(qū)域
- 給品牌添加鼠標移去事件
- 給品牌添加點擊事件,把點擊品牌顯示到input上
- 給車系添加鼠標移上事件,當前車系為選中狀態(tài),其對應的車型顯示在車型區(qū)域,其所屬的品牌為選中狀態(tài)
- 給車系添加鼠標移去事件
- 給車系添加點擊事件,把點擊車系和所屬品牌顯示到input上,以逗號隔開
- 給車型添加鼠標移上事件,當前車型為選擇狀態(tài),其所屬父類車系為選中狀態(tài),車型所屬父類品牌也為選中狀態(tài)
- 給車型添加點擊事件,把點擊車型和所屬車系、品牌顯示到input上,以逗號隔開
- 給關閉按鈕添加點擊事件,關閉div,并解除頁面空白區(qū)域點擊事件的綁定
領域先行,首先是有關品牌、車系、車型的模型:
public class CarCategory
{
public int Id { get; set; }
public string Name { get; set; }
public int PId { get; set; }
public string FirstLetter { get; set; }
public string AnchorName { get; set; }
public int Level { get; set; }
}- PId屬性用來表示父類Id,車系的父類Id為某個品牌Id,車型的父類Id為某個車系Id
- FirstLetter屬性用來表示首字母,作為分組的條件
- AnchorName屬性用來表示品牌的錨點id,車系和車型此項為空
在ASP.NET MVC4中,在Shared/Layout.cshtml中,該有的css,js都必須有:
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>@ViewBag.Title</title>
@Styles.Render("~/Content/css")
@RenderSection("styles", required: false)
<link href="~/bootstrap/css/bootstrap.min.css" rel="stylesheet" />
@Scripts.Render("~/bundles/jquery")
<script src="~/bootstrap/js/bootstrap.min.js"></script>
</head>
<body>
@RenderBody()
@RenderSection("scripts", required: false)
</body>模擬一個數據庫,該數據庫類可以獲取到所有的品牌、車系、車型,以及根據品牌Id或車系Id獲取對應的車系和車型。
public class Database
{
public static IEnumerable<CarCategory> GetCarCategories()
{
return new List<CarCategory>()
{
new CarCategory(){Id = 0, Name = "奧迪",FirstLetter = "A",AnchorName = "aa", Level = 1, PId = -1},
new CarCategory(){Id = 1, Name = "奧斯頓·馬丁",FirstLetter = "A",AnchorName = "aa", Level = 1, PId = -1},
new CarCategory(){Id = 2, Name = "寶駿",FirstLetter = "B",AnchorName = "bb", Level = 1, PId = -1},
new CarCategory(){Id = 3, Name = "巴博斯",FirstLetter = "B",AnchorName = "bb", Level = 1, PId = -1},
new CarCategory(){Id = 4, Name = "北汽威旺",FirstLetter = "B",AnchorName = "bb", Level = 1, PId = -1},
new CarCategory(){Id = 5, Name = "北汽制造",FirstLetter = "B",AnchorName = "bb", Level = 1, PId = -1},
new CarCategory(){Id = 6, Name = "奔馳",FirstLetter = "B",AnchorName = "bb", Level = 1, PId = -1},
new CarCategory(){Id = 7, Name = "別克",FirstLetter = "B",AnchorName = "bb", Level = 1, PId = -1},
new CarCategory(){Id = 8, Name = "賓利",FirstLetter = "B",AnchorName = "bb", Level = 1, PId = -1},
new CarCategory(){Id = 9, Name = "保時捷",FirstLetter = "B",AnchorName = "bb", Level = 1, PId = -1},
new CarCategory(){Id = 10, Name = "比亞迪",FirstLetter = "B",AnchorName = "bb", Level = 1, PId = -1},
new CarCategory(){Id = 11, Name = "奔騰",FirstLetter = "B",AnchorName = "bb", Level = 1, PId = -1},
new CarCategory(){Id = 12, Name = "標致",FirstLetter = "B",AnchorName = "bb", Level = 1, PId = -1},
new CarCategory(){Id = 13, Name = "本田",FirstLetter = "B",AnchorName = "bb", Level = 1, PId = -1},
new CarCategory(){Id = 14, Name = "寶馬",FirstLetter = "B",AnchorName = "bb", Level = 1, PId = -1},
new CarCategory(){Id = 15, Name = "北京汽車",FirstLetter = "B",AnchorName = "bb", Level = 1, PId = -1},
new CarCategory(){Id = 16, Name = "昌河",FirstLetter = "C",AnchorName = "cc", Level = 1, PId = -1},
new CarCategory(){Id = 17, Name = "長安",FirstLetter = "C",AnchorName = "cc", Level = 1, PId = -1},
new CarCategory(){Id = 18, Name = "長城",FirstLetter = "C",AnchorName = "cc", Level = 1, PId = -1},
new CarCategory(){Id = 19, Name = "奧迪A4",FirstLetter = "A",AnchorName = "", Level = 2, PId = 0},
new CarCategory(){Id = 20, Name = "奧迪A6L",FirstLetter = "A",AnchorName = "", Level = 2, PId = 0},
new CarCategory(){Id = 21, Name = "奧迪Q3",FirstLetter = "A",AnchorName = "", Level = 2, PId = 0},
new CarCategory(){Id = 22, Name = "奧迪A4舒適版",FirstLetter = "A",AnchorName = "", Level = 3, PId = 19},
new CarCategory(){Id = 23, Name = "奧迪A4尊貴版",FirstLetter = "A",AnchorName = "", Level = 3, PId = 19},
new CarCategory(){Id = 24, Name = "奧迪A6L舒適版",FirstLetter = "A",AnchorName = "", Level = 3, PId = 20},
new CarCategory(){Id = 25, Name = "奧迪A6L黃金版",FirstLetter = "A",AnchorName = "", Level = 3, PId = 20},
new CarCategory(){Id = 26, Name = "奧迪Q3舒適版",FirstLetter = "A",AnchorName = "", Level = 3, PId = 21},
new CarCategory(){Id = 27, Name = "奧迪Q3至尊版",FirstLetter = "A",AnchorName = "", Level = 3, PId = 21},
};
}
//根據品牌或車系I獲取所有車系或車型
public static IEnumerable<CarCategory> GetCarCategoriesByPId(int pid)
{
return GetCarCategories().Where(c => c.PId == pid);
}
} 在HomeController中,在前端頁面加載的時候,這里提供一個分組好的所有品牌的json格式給前端;當前端把鼠標移動到某個品牌上,這里根據品牌Id返回車系的json格式給前端;當前端把鼠標移動到某個車系上,這里根據車系Id返回車型的json格式給前端。
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
//獲取所有品牌
public ActionResult GetPinPai()
{
var allPinPai = Database.GetCarCategories().Where(c => c.Level == 1).OrderBy(c => c.Id);
var result = from p in allPinPai
group p by new
{
p.FirstLetter,
p.AnchorName
}
into g
select new {firstletter = g.Key.FirstLetter, anchor = g.Key.AnchorName, pinpais = g};
return Json(result, JsonRequestBehavior.AllowGet);
}
//根據品牌Id獲取車系
[HttpPost]
public ActionResult GetCheXiByPId(int pid)
{
var allCheXi = Database.GetCarCategoriesByPId(pid).OrderBy(c => c.Id);
var result = from c in allCheXi
select new {chexi = c.Name, cxid = c.Id, parentId = c.PId};
return Json(result);
}
//根據車系Id獲取車型
[HttpPost]
public ActionResult GetCheXingByCxId(int cxid)
{
var allCheXing = Database.GetCarCategoriesByPId(cxid).OrderBy(c => c.Id);
var result = from c in allCheXing
select new { chexing = c.Name, chexingid = c.Id, parentId = c.PId };
return Json(result);
}
} 在Home/Index.cshtml視圖中,品牌、車系、車型內容都是先填充到tmpl模版中,然后追加到頁面某個區(qū)域上的。
@{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
@section styles
{
<link href="~/Content/CarSelect.css" rel="external nofollow" rel="stylesheet" />
}
<div class="input-group">
<input type="text" id="mychoice" class="form-control">
<span class="input-group-btn">
<button class="btn btn-default" type="button">∨</button>
</span>
</div>
<div id="carcategory-picker-outer">
<a href="javascript:void(0)" rel="external nofollow" class="cancel"></a>
<div id="carcategory-picker-inner">
<div id="pinpai" class="carcategory-list">
<h6>請選擇品牌</h6>
<div id="PreLetter">
<a href="#aa" rel="external nofollow" >A</a>
<a href="#bb" rel="external nofollow" >B</a>
<a href="#cc" rel="external nofollow" >C</a>
<a href="#dd" rel="external nofollow" >D</a>
<a href="#ff" rel="external nofollow" >F</a>
<a href="#gg" rel="external nofollow" >G</a>
<a href="#hh" rel="external nofollow" >H</a>
<a href="#jj" rel="external nofollow" >J</a>
<a href="#kk" rel="external nofollow" >K</a>
<a href="#ll" rel="external nofollow" >L</a>
<a href="#mm" rel="external nofollow" >M</a>
<a href="#nn" rel="external nofollow" >N</a>
<a href="#oo" rel="external nofollow" >O</a>
<a href="#qq" rel="external nofollow" >Q</a>
<a href="#rr" rel="external nofollow" >R</a>
<a href="#ss" rel="external nofollow" >S</a>
<a href="#ww" rel="external nofollow" >W</a>
<a href="#xx" rel="external nofollow" >X</a>
<a href="#yy" rel="external nofollow" >Y</a>
<a href="#zz" rel="external nofollow" >Z</a>
</div>
<div id="AllPinPai">
</div>
</div>
<div id="chexi" class="carcategory-list">
<h6>請選擇車系</h6>
<div id="AllCheXi">
</div>
</div>
<div id="chexin" class="carcategory-list">
<h6>請選擇車型</h6>
<div id="AllCheXing">
</div>
</div>
</div>
</div>
@section scripts
{
<script src="~/Scripts/jquery.tmpl.min.js"></script>
<script type="text/javascript">
$(function() {
//加載所有品牌
$.getJSON('@Url.Action("GetPinPai", "Home")', function(data) {
$('#pinpaiTemplate').tmpl(data).appendTo('#AllPinPai');
});
//點擊input彈出品牌車系車型選擇
$('#mychoice').on("click", function() {
$('#carcategory-picker-outer').css('display', 'block');
$("body").bind("mousedown", onBodyDown);//綁定鼠標單擊事件
});
//點擊關閉按鈕隱藏品牌車系車型選擇
$('.cancel').on("click", function() {
hideMenu();
});
//給所有品牌加上鼠標移動上事件
$('#AllPinPai').on("mouseover", ".ppm", function() {
$(this).addClass('selected');
$('#chexi').css("display", "block");
$.post('@Url.Action("GetCheXiByPId","Home")', { 'pid': $(this).attr('pid') }, function (data) {
$('#AllCheXi').empty();
$('#AllCheXing').empty();
$('#chexiTemplate').tmpl(data).appendTo('#AllCheXi');
});
});
//給所有品牌加上鼠標移去事件
$('#AllPinPai').on("mouseout", ".ppm", function () {
$(this).removeClass('selected');
});
//品牌點擊事件
$('#AllPinPai').on("click", ".ppm", function () {
$('#mychoice').val('');
$('#mychoice').val($(this).text());
hideMenu();
});
//給車系加上鼠標移動上事件
$('#AllCheXi').on("mouseover", ".cxm", function () {
//取取當前車系的父類Id
var parentId = $(this).attr('parentid');
//把品牌中該父類添加selected這個類
$('#AllPinPai').find("a[pid='" + parentId + "']").addClass('selected');
$(this).addClass('selected');
$('#chexin').css("display", "block");
$.post('@Url.Action("GetCheXingByCxId","Home")', { 'cxid': $(this).attr('pid') }, function (data) {
$('#AllCheXing').empty();
$('#chexingTemplate').tmpl(data).appendTo('#AllCheXing');
});
});
//給車系加上鼠標移去事件
$('#AllCheXi').on("mouseout", ".cxm", function () {
$(this).removeClass('selected');
//取取當前車系的父類Id
var parentId = $(this).attr('parentid');
//把品牌中該父類添加selected這個類
$('#AllPinPai').find("a[pid='" + parentId + "']").removeClass('selected');
});
//車系點擊事件
$('#AllCheXi').on("click", ".cxm", function () {
$('#mychoice').val('');
//取取當前車系的父類Id
var parentId = $(this).attr('parentid');
$('#mychoice').val($('#AllPinPai').find("a[pid='" + parentId + "']").text() + "," + $(this).text());
hideMenu();
});
//給車型加上鼠標移上事件
$('#AllCheXing').on("mouseover", ".cxim", function () {
//取出車型的父類id
var parentId = $(this).attr('parentid');
//把車系中該父類添加selected這個類
$('#AllCheXi').find("a[pid='" + parentId + "']").addClass('selected');
//取出車系的父類id
var parentparentId = $('#AllCheXi').find("a[pid='" + parentId + "']").attr('parentid');
//把品牌中該父類添加selected這個類
$('#AllPinPai').find("a[pid='" + parentparentId + "']").addClass('selected');
});
//給車型加上鼠標移去事件
$('#AllCheXing').on("mouseout", ".cxim", function () {
//取出車型的父類id
var parentId = $(this).attr('parentid');
//把車系中該父類添加selected這個類
$('#AllCheXi').find("a[pid='" + parentId + "']").removeClass('selected');
//取出車系的父類id
var parentparentId = $('#AllCheXi').find("a[pid='" + parentId + "']").attr('parentid');
//把品牌中該父類添加selected這個類
$('#AllPinPai').find("a[pid='" + parentparentId + "']").removeClass('selected');
});
//車型點擊事件
$('#AllCheXing').on("click", ".cxim", function () {
$('#mychoice').val('');
//取出車型的父類id
var parentId = $(this).attr('parentid');
//取出車系的父類id
var parentparentId = $('#AllCheXi').find("a[pid='" + parentId + "']").attr('parentid');
$('#mychoice').val($('#AllPinPai').find("a[pid='" + parentparentId + "']").text() + "," + $('#AllCheXi').find("a[pid='" + parentId + "']").text() + "," + $(this).text());
hideMenu();
});
});
//隱藏樹并解除綁定
function hideMenu() {
$("#carcategory-picker-outer").fadeOut("fast");
$("body").unbind("mousedown", onBodyDown);
}
//鼠標單擊空白處事件
function onBodyDown(event) {
if (!(event.target.id == "mychoice" || event.target.id == "carcategory-picker-outer" || $(event.target).parents("#carcategory-picker-outer").length > 0)) {
hideMenu();
}
}
</script>
<script id="pinpaiTemplate" type="text/x-jQuery-tmpl">
<dl>
<dt id="${anchor}">${firstletter}</dt>
{{if pinpais}}
{{each pinpais}}<dd><a class="ppm" pid="${$value.Id}">${$value.Name}</a></dd>{{/each}}
{{else}}
<dd>沒有此品牌</dd>
{{/if}}
</dl>
</script>
<script id="chexiTemplate" type="text/x-jQuery-tmpl">
<dl>
<dd><a class="cxm" pid="${cxid}" parentid="${parentId}">${chexi}</a></dd>
</dl>
</script>
<script id="chexingTemplate" type="text/x-jQuery-tmpl">
<dl>
<dd><a class="cxim" pid="${chexingid}" parentid="${parentId}">${chexing}</a></dd>
</dl>
</script>
}css部分如下,關閉按鈕可自找。
#carcategory-picker-outer {
background: #f9f9f9;
padding: 10px;
width: 640px;
height: 380px;
position: relative;
display: none;
}
#PreLetter {
border: 0px solid blue;
width: 21px;
float: left;
}
#PreLetter a:link{
display: block;
text-decoration: none;
clear: both;
font-size: 10px;
text-align: center;
padding-top: 0px;
border: 1px solid #e3e3e3;
width: 15px;
height: 15px;
background-color: #e9e9e9;
margin-top: 2px;
font-weight: bold;
}
#PreLetter a:hover {
border: 1px solid blue;
}
#PreLetter a:visited {
border: 1px solid #e3e3e3;
}
#pinpai {
border: 0px solid green;
float: left;
}
#AllPinPai {
border: 1px solid #e3e3e3;
margin-left: 5px;
float: left;
padding-bottom: 0px;
width: 120px;
height: 340px;
overflow-y: auto;
}
#AllPinPai dl dd a {
text-decoration: none;
display: block;
padding-left: 10px;
}
#AllPinPai dl dd {
padding-left: 0px;
}
#AllPinPai dl dd a:hover {
/*background-color: gray;*/
color: white;
}
#AllPinPai dl {
margin-bottom: 5px;
}
#chexi {
border: 0px solid orange;
float: left;
margin-left: 10px;
display: none;
}
#AllCheXi {
width: 150px;
height: 340px;
overflow-y: auto;
border: 1px solid #e3e3e3;
}
#AllCheXi dl dd a {
text-decoration: none;
display: block;
padding-left: 10px;
}
#AllCheXi dl dd {
padding-left: 0px;
}
#AllCheXi dl dd a:hover {
color: white;
}
#AllCheXi dl {
margin-bottom: 5px;
}
#chexin {
border: 0px solid red;
float: left;
margin-left: 10px;
display: none;
}
#AllCheXing {
width: 300px;
height: 340px;
overflow-y: auto;
border: 1px solid #e3e3e3;
}
#AllCheXing dl dd a {
text-decoration: none;
display: block;
padding-left: 10px;
}
#AllCheXing dl dd {
padding-left: 0px;
}
#AllCheXing dl dd a:hover {
background-color: gray;
color: white;
}
#AllCheXing dl {
margin-bottom: 5px;
}
dt {
background-color: #e9e9e9;
padding-left: 10px;
}
dl {
border: 0px solid red;
}
dd {
padding-left: 10px;
line-height: 15px;
margin-top: 5px;
margin-bottom: 0px;
border: 0px solid blue;
/*background-color: gray;*/
}
.selected {
background-color: gray;
color: white;
}
.cancel {
width: 20px;
height: 17px;
position: absolute;
display: block;
top: 20px;
right: 20px;
background-image: url("../img/close.png");
border: 1px solid orangered;
background-color: orangered;
}
.input-group {
width: 640px;
}以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對腳本之家的支持。如果你想了解更多相關內容請查看下面相關鏈接
相關文章
詳解ASP.NET Core 之 Identity 入門(三)
本篇文章主要介紹了ASP.NET Core 之 Identity 入門,主要負責對用戶的身份進行認證,有興趣的可以了解一下。2016-12-12
Asp.net(C#)讀取數據庫并生成JS文件制作首頁圖片切換效果(附demo源碼下載)
這篇文章主要介紹了Asp.net(C#)讀取數據庫并生成JS文件制作首頁圖片切換效果的方法,涉及asp.net數據庫操作及JavaScript幻燈片生成的相關技巧,并附帶demo源碼供讀者下載參考,需要的朋友可以參考下2016-04-04
asp.net Menu控件+SQLServer實現動態(tài)多級菜單
asp.net Menu控件+SQLServer實現動態(tài)多級菜單的代碼,需要的朋友可以參考下。2011-12-12

