省市县乡村 动态级联加载控件AreaRender(一)
最近在做项目的时候需要对用户的籍贯和所在地的加载问题,以前也遇到过这个问题,只是临时应付了一下.
最近觉得这个以后还要用到,所以就重新整理了思路,写出一个尽量通用的全国区划动态加载的扩展方法。
首先分析一下需求:加载某个用户的信息时,需要将该用户的籍贯和所在地展示出来,还可以让其修改。
思路:初次加载时,将地址信息隐藏起来,而后根据隐藏的值逐级给select赋值。
初始化阶段:
1.首先加载省份信息;
2.将隐藏域中省份的值赋给select,在此根据隐藏域中的值加载市的信息;
3.一次类推,直到加载到村,或者没有默认值为止。
修改阶段:
1.将所有的select的选中的值赋值给隐藏域;
2.加载下一级数据。
接下来我们自上往下讲解代码编写过程。
1.新建asp.net mvc 3 的项目
2.在index.cshtml文件中调用控件
@model List<DynamicArea.Models.ChinaArea> @using DynamicArea.Helpers @{ ViewBag.Title = "测试地区的级联加载"; Layout = "~/Views/Shared/_Layout.cshtml"; <script src="http://www.cnblogs.com/Scripts/InitNextLevle.js" type="text/javascript"></script> <script src="http://www.cnblogs.com/Scripts/AddNextLevel.js" type="text/javascript"></script> <script src="http://www.cnblogs.com/Scripts/SetValue.js" type="text/javascript"></script> <script src="http://www.cnblogs.com/Scripts/AddProvince.js" type="text/javascript"></script> } @using (Html.BeginForm("Save", "Home")) { @Html.AreaRender(ViewBag.ds1 as Dictionary<string, string>, ViewBag.provinceUrl as string, ViewBag.nextUrl as string) @Html.AreaRender(ViewBag.ds2 as Dictionary<string, string>, ViewBag.provinceUrl as string, ViewBag.nextUrl as string) }
大家可以看到,我们需要提供三个参数,从中也可以看到参数的类型:
ViewBag.ds1 as Dictionary<string, string>, ViewBag.provinceUrl as string, ViewBag.nextUrl as string
接下来看控制器中如何提供这些参数
public class HomeController : Controller { public ActionResult Index() { //新疆维吾尔自治区:650000000000 //乌鲁木齐市 :650100000000 //天山区 :650102000000 //燕儿窝街道 :650102002000 //燕儿窝南社区居委会:650102002002 Dictionary<string, string> ds1 = new Dictionary<string, string>(); ds1.Add("pro.id", "650000000000"); ds1.Add("cit.id", "650100000000"); ds1.Add("cou.id", "650102000000"); ds1.Add("tow.id", "650102002000"); ds1.Add("vil.id", "650102002002"); ds1.Add("pro.name", "新疆维吾尔自治区"); ds1.Add("cit.name", "乌鲁木齐市"); ds1.Add("cou.name", "天山区"); ds1.Add("tow.name", "燕儿窝街道"); ds1.Add("vil.name", "燕儿窝南社区居委会"); ViewBag.ds1 = ds1; ViewBag.ds2 = ds1; ViewBag.provinceUrl = "/Home/GetProvinces"; ViewBag.nextUrl = "/Home/GetNextLevel"; return View(); } [HttpPost] public ActionResult Save(FormCollection fc) { Area area = new Area(); UpdateModel(area, fc); return Index(); } [HttpPost] public JsonResult GetProvinces() { DArea da = new DArea(); var allProvinces = da.ChinaAreas.Where(ca => ca.ParentID == null); return Json(allProvinces.ToArray(), JsonRequestBehavior.AllowGet); } [HttpPost] public JsonResult GetNextLevel(string code) { try { if (code == null) { return null; } DArea da = new DArea(); int id = da.ChinaAreas.Where(ca => ca.Code == code).First().Id; var nextlevel = da.ChinaAreas.Where(ca => ca.ParentID == id); return Json(nextlevel.ToArray(), JsonRequestBehavior.AllowGet); } catch (Exception) { return null; } } }
好的,目前我们站在使用者的角度写出这些代码。
接下来我们要实现@Html.AreaRender这个扩展方法。
向图1中的Hhelpers文件中添加一个静态类AreaRenderHelper
public static class AreaRenderHelper { /// <summary> /// 动态级联加载区划(省,市,县,乡,村) /// </summary> /// <param name="htmlhelper">扩展方法的指定参数</param> /// <param name="nameAndvalue">提供字段名称和取值的字典</param> /// <param name="getProvinceUrl">获取省份数据的路径名称</param> /// <param name="getNextLevelUrl">获取下一级数据的路径名称</param> /// <returns></returns> public static MvcHtmlString AreaRender( this HtmlHelper htmlhelper, Dictionary<string, string> nameAndvalue, string getProvinceUrl, string getNextLevelUrl) { MvcHtmlString mhs = htmlhelper.Partial("~/Views/AreaManager/AreaRender.cshtml", new { data = nameAndvalue, provinceUrl = getProvinceUrl, nextUrl = getNextLevelUrl }.ToExpando()); return mhs; } }
在静态类AreaRenderHelper中我们看到.ToExpando() 方法,这个方法是要手动添加的,他是第三方提供的命名空间是System的扩展方法。
using System; using System.Collections.Generic; using System.Dynamic; using System.Linq; using System.Web; using System.Web.Mvc; namespace System { public static class ExpandoHelper { public static ExpandoObject ToExpando(this object anonymousObject) { IDictionary<string, object> anonymousDictionary = HtmlHelper.AnonymousObjectToHtmlAttributes(anonymousObject); IDictionary<string, object> expando = new ExpandoObject(); foreach (var item in anonymousDictionary) expando.Add(item); return (ExpandoObject)expando; } } }
把该类也加在Helpers文件夹中吧。这个无所谓因为他的命名空间是:System
好的,该下班了,明天接着写控件所需的js。谢谢!