前段时间参与一个公司的项目,使用ASP.NET MVC 3.0,其中有多处使用了级联下拉。
考虑到这种ajax异步调用代码重复且不方便调试,于是做了一个公用控件,实际是一个.NET MVC的PartialView。
PartialView:
SelectView.cshtml
@model Platform.Modules.Base.ViewModels.SelectViewModel <select id="@Model.Id" name="@Model.Name" class="@Model.Class" style="@Model.Style"><option value='@Model.DefaultValue'>@Model.DefaultText</option></select> <script type="text/javascript"> $(function () { var actionUrl = '@Model.ActionUrl'; var unselected = "<option value='@Model.DefaultValue'>@Model.DefaultText</option>"; var tagId,textProperty,valueProperty,parentTagId,paramName,currentSelectedValue,requestMethod; tagId = '@Model.Id'; textProperty='@Model.TextProperty'; valueProperty='@Model.ValueProperty'; parentTagId='@Model.ParentTagId'; paramName='@Model.ParamName'; currentSelectedValue='@Model.SelectedValue'; requestMethod='@Model.RequestMethod.ToString()'; @{if(String.IsNullOrEmpty(Model.ParentTagId)){ <text> $.ajax({ type: requestMethod, url: actionUrl+"?ts="+new Date().getTime(), cache:false, success: function(data){ $("#" + tagId).empty(); $("#" + tagId).append(unselected); $.each(data, function (i, item) { if($(item).attr(valueProperty)==currentSelectedValue){ $("#" + tagId).append($("<option selected='selected' value='" + $(item).attr(valueProperty) + "'>" + $(item).attr(textProperty) + "</option>")); }else{ $("#" + tagId).append($("<option value='" + $(item).attr(valueProperty) + "'>" + $(item).attr(textProperty) + "</option>")); } }); }, complete:function() { if(currentSelectedValue!=null){ if($('#'+tagId).fireEvent) $('#'+tagId).fireEvent("onchange"); else $('#'+tagId).change(); } } }); </text> }else{ <text> $("#" + parentTagId).change(function () { $('#'+tagId).empty(); $('#'+tagId).append(unselected); if($('#'+tagId).fireEvent) $('#'+tagId).fireEvent("onchange"); else $('#'+tagId).change(); var parentValue = $(this).val(); if (!parentValue) { return; } $.ajax({ type: requestMethod, url: actionUrl+"?ts="+new Date().getTime(), data: paramName+"=" + parentValue, cache:false, success: function(data){ $.each(data, function (i, item) { if($(item).attr(valueProperty)==currentSelectedValue){ $("#" + tagId).append($("<option selected='selected' value='" + $(item).attr(valueProperty) + "'>" + $(item).attr(textProperty) + "</option>")); }else{ $("#" + tagId).append($("<option value='" + $(item).attr(valueProperty) + "'>" + $(item).attr(textProperty) + "</option>")); } }); }, complete:function() { if(currentSelectedValue!=null){ if($('#'+tagId).fireEvent) $('#'+tagId).fireEvent("onchange"); else $('#'+tagId).change(); } } }); }); </text> } } }); </script>
该控件使用到的Model类:
SelectViewModel.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Web.Mvc; namespace Platform.Modules.Base.ViewModels { public class SelectViewModel { /// <summary> /// select标签Id /// </summary> public String Id { get; set; } /// <summary> /// select标签Name /// </summary> public String Name { get; set; } /// <summary> /// json数据源元素中代表select>option>Text的属性 /// </summary> public String TextProperty { get; set; } /// <summary> /// json数据源元素中代表select>option>value的属性 /// </summary> public String ValueProperty { get; set; } /// <summary> /// 数据源获取地址 /// </summary> public String ActionUrl { get; set; } /// <summary> /// select标签初始项文本,默认为空字符串 /// </summary> public String DefaultText { get; set; } /// <summary> /// select标签初始项值,默认为空字符串 /// </summary> public String DefaultValue{ get; set; } /// <summary> /// 获取数据时传递的参数名 /// </summary> public String ParamName { get; set; } /// <summary> /// 父级下拉框的标签id /// 有父级必选 /// </summary> public String ParentTagId { get; set; } /// <summary> /// 样式表 /// </summary> public String Class { get; set; } /// <summary> /// 样式 /// </summary> public String Style { get; set; } /// <summary> /// select标签当前选定项 /// </summary> public String SelectedValue { get; set; } private FormMethod requestMethod = FormMethod.Get; /// <summary> /// 请求方式 /// 默认为GET /// </summary> public FormMethod RequestMethod { get { return requestMethod; } set { requestMethod = value; } } } }
Demo:
Ajax回调的Action
public ActionResult GetProvinces() { var entities = locationService.GetProvinceList(); return Json(entities, JsonRequestBehavior.AllowGet); } public ActionResult GetCities(String provinceCode) { var entities = locationService.GetCityList(new CityQuery() { ProvinceCode = provinceCode }); return Json(entities, JsonRequestBehavior.AllowGet); } public ActionResult GetCounties(String cityCode) { var entities = locationService.GetCountyList(new CountyQuery() { CityCode = cityCode }); return Json(entities, JsonRequestBehavior.AllowGet); } /// <summary> /// 测试页Action /// </summary> /// <returns></returns> public ActionResult SelectControlTest() { return View(); }
测试页面(省市县三级联动)
@{ ViewBag.Title = "SelectControlTest"; } @using Platform.Modules.Base.ViewModels <h2>SelectControlTest</h2> 省:@{Html.RenderPartial("SelectView", new SelectViewModel() { ActionUrl = Url.Action("GetProvinces", "Location"), DefaultText = "---请选择---", DefaultValue = "", Id = "aaaaa", Name = "aaaaa", TextProperty = "Name", ValueProperty = "Code", Style = "173px", });} 市:@{Html.RenderPartial("SelectView",new SelectViewModel(){ ActionUrl = Url.Action("GetCities", "Location"), DefaultText="---请选择---", DefaultValue="", Id="bbbbbb", ParentTagId="aaaaa", ParamName = "provinceCode", Name="bbbbbb", TextProperty="Name", ValueProperty = "Code", Style = "173px" });} 县:@{Html.RenderPartial("SelectView",new SelectViewModel(){ ActionUrl = Url.Action("GetCounties", "Location"), DefaultText="---请选择---", DefaultValue="", Id="cccccc", ParamName = "cityCode", ParentTagId="bbbbbb", Name="cccccc", TextProperty="Name", ValueProperty="Code", Style = "173px" });}
理论上支持无限级联。。
支持Post,Get两种请求方式。默认使用Get方式。
注意:使用Get方式请求Action,返回JSON的时候一定要加JsonRequestBehavior.AllowGet。