ASP.NET MVC實現城市或車型三級聯動
三級或多級聯動的場景經常會碰到,比如省、市、區,比如品牌、車系、車型,比如類別的多級聯動......我們首先想到的是用三個select來展示,這是最通常的做法。但在另外一些場景中,比如確定搜索條件的時候,對于三級聯動來說,可能選擇1個,2個,或3個條件,我想,以下的方式可能更適合:
以上,可以只選擇品牌,或同時選擇品牌、車系,或同時選擇品牌、車系、車型,最后把選擇的內容展示到input上,并以逗號隔開。
可以實現的功能包括:
- 點擊最上面的input彈出div,此時只顯示品牌區域
- 點擊最左邊拼音首字母,導航到對應的品牌上
- 當把鼠標移動到某個品牌上,品牌為選中狀態,其對應的車系顯示在車系區域
- 當鼠標不在任何品牌上,所有品牌都為不選中狀態
- 當把鼠標移動到某個車系上,車系為選中狀態,其對應的車型顯示在車型區域,選中車系的所屬品牌也為選中狀態
- 當鼠標不在任何車系上,所有車系、品牌都為不選中狀態
- 當把鼠標移動到某個車型上,車型為選中狀態,選中車型的所屬車系為選中狀態,選中車系所屬品牌為選中狀態
- 當鼠標不在任何車型上,所有車型、車系、品牌為不選中狀態
- 點擊品牌,品牌顯示到input上
- 點擊車系,品牌、車系顯示到input上,并以逗號隔開
- 點擊車型,品牌、車系、車型顯示到input上,并以逗號隔開
- 點擊div上的關閉按鈕或者頁面空白區域,div隱藏
界面的構成如下:
- 最上面的是一個input
- 品牌、車系、車型被包裹在一個div中,點擊關閉按鈕或點擊空白處關閉的就是這個div
- 品牌區域是一個div,分為首字母導航div和品牌顯示div
- 車系區域是一個div
- 車型區域是一個div
- 品牌、車系、車型內的內容是一些dl, dt, dd的html元素
- 樣式的事情交給css
實現的思路大致這樣:
- 給input點擊事件,點擊彈出品牌、車系、車型顯示的div,并綁定頁面空白區域的點擊事件
- 導航首字母指向錨點,品牌按首字母分類并提供錨點id
- 在控制器中把品牌按照首字母分類,以json格式返回到前端,填充到tmpl模版,再追加到頁面品牌區域
- 給品牌添加鼠標移上事件,品牌為選中狀態,對應的車系顯示在車系區域
- 給品牌添加鼠標移去事件
- 給品牌添加點擊事件,把點擊品牌顯示到input上
- 給車系添加鼠標移上事件,當前車系為選中狀態,其對應的車型顯示在車型區域,其所屬的品牌為選中狀態
- 給車系添加鼠標移去事件
- 給車系添加點擊事件,把點擊車系和所屬品牌顯示到input上,以逗號隔開
- 給車型添加鼠標移上事件,當前車型為選擇狀態,其所屬父類車系為選中狀態,車型所屬父類品牌也為選中狀態
- 給車型添加點擊事件,把點擊車型和所屬車系、品牌顯示到input上,以逗號隔開
- 給關閉按鈕添加點擊事件,關閉div,并解除頁面空白區域點擊事件的綁定
領域先行,首先是有關品牌、車系、車型的模型:
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 allPinPaigroup p by new{ p.FirstLetter, p.AnchorName}into gselect 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 allCheXiselect 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模版中,然后追加到頁面某個區域上的。
@{ ViewBag.Title = "Index"; Layout = "~/Views/Shared/_Layout.cshtml";}@section styles{ <link href="~/Content/CarSelect.css" rel="external nofollow" rel="stylesheet" />}<div> <input type="text" id="mychoice"> <span><button type="button">∨</button> </span></div><div id="carcategory-picker-outer"> <a href="javascript:void(0)" rel="external nofollow" ></a> <div id="carcategory-picker-inner"><div id="pinpai"> <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"> <h6>請選擇車系</h6> <div id="AllCheXi"> </div></div><div id="chexin"> <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 () {//取取當前車系的父類Idvar 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");//取取當前車系的父類Idvar parentId = $(this).attr("parentid");//把品牌中該父類添加selected這個類$("#AllPinPai").find("a[pid="" + parentId + ""]").removeClass("selected"); }); //車系點擊事件 $("#AllCheXi").on("click", ".cxm", function () {$("#mychoice").val("");//取取當前車系的父類Idvar parentId = $(this).attr("parentid");$("#mychoice").val($("#AllPinPai").find("a[pid="" + parentId + ""]").text() + "," + $(this).text());hideMenu(); }); //給車型加上鼠標移上事件 $("#AllCheXing").on("mouseover", ".cxim", function () {//取出車型的父類idvar parentId = $(this).attr("parentid");//把車系中該父類添加selected這個類$("#AllCheXi").find("a[pid="" + parentId + ""]").addClass("selected");//取出車系的父類idvar parentparentId = $("#AllCheXi").find("a[pid="" + parentId + ""]").attr("parentid");//把品牌中該父類添加selected這個類$("#AllPinPai").find("a[pid="" + parentparentId + ""]").addClass("selected"); }); //給車型加上鼠標移去事件 $("#AllCheXing").on("mouseout", ".cxim", function () {//取出車型的父類idvar parentId = $(this).attr("parentid");//把車系中該父類添加selected這個類$("#AllCheXi").find("a[pid="" + parentId + ""]").removeClass("selected");//取出車系的父類idvar parentparentId = $("#AllCheXi").find("a[pid="" + parentId + ""]").attr("parentid");//把品牌中該父類添加selected這個類$("#AllPinPai").find("a[pid="" + parentparentId + ""]").removeClass("selected"); }); //車型點擊事件 $("#AllCheXing").on("click", ".cxim", function () {$("#mychoice").val("");//取出車型的父類idvar parentId = $(this).attr("parentid");//取出車系的父類idvar 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 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 pid="${cxid}" parentid="${parentId}">${chexi}</a></dd></dl> </script> <script id="chexingTemplate" type="text/x-jQuery-tmpl"><dl> <dd><a 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;}
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對的支持。如果你想了解更多相關內容請查看下面相關鏈接
相關文章:
1. ASP.NET MVC通過勾選checkbox更改select的內容2. ASP.NET MVC視圖頁使用jQuery傳遞異步數據的幾種方式詳解3. ASP.NET MVC使用JSAjaxFileUploader插件實現單文件上傳4. ASP.NET MVC增加一條記錄同時添加N條集合屬性所對應的個體5. ASP.NET MVC實現橫向展示購物車6. ASP.NET MVC使用Boostrap實現產品展示、查詢、排序、分頁7. ASP.NET MVC前臺動態添加文本框并在后臺使用FormCollection接收值8. ASP.NET MVC限制同一個IP地址單位時間間隔內的請求次數9. ASP.NET MVC解決上傳圖片臟數據的方法10. ASP.NET MVC實現單個圖片上傳、限制圖片格式與大小并在服務端裁剪圖片
