手把手教你 Nopcommerce2.6 之实现中国国家/省/市/区县功能,废话少说,直切主题!
第一步:修改数据表 StateProvince 增加字段ParentId以实现递归。如图:
第二步:在Nop.Admin.Models.Directory 下为 StateProvinceModel 模型增加成员
public int ParentId { get; set; } // 面包屑方式呈现 public string Breadcrumb { get; set; } // 省份级DropDownList public IList<DropDownItem> ParentProvinces { get; set; }
第三步:在 Nop.Core.Domain.Directory 下为 StateProvince 增加成员
/// <summary> /// 父类标识 /// </summary> public virtual int ParentId { get; set; }
第四步:在 Nop.Services.Directory 下增加扩展方法 StateProvinceExtensions 以实现省市区县面包屑呈现。
代码如下:
using System; using Nop.Core.Domain.Directory; namespace Nop.Services.Directory { /// <summary> /// IStateProvinceService 扩展方法 /// [email protected] 2012年8月2日16:40:32 /// </summary> public static class StateProvinceExtensions { /// <summary> /// 省市区县面包屑呈现 /// </summary> /// <param name="stateProvince"></param> /// <param name="stateProvinceService"></param> /// <returns></returns> public static string GetStateProvinceBreadCrumb(this StateProvince stateProvince, IStateProvinceService stateProvinceService) { string result = string.Empty; while (stateProvince != null) { if (String.IsNullOrEmpty(result)) result = stateProvince.Name; else result = stateProvince.Name + " >> " + result; stateProvince = stateProvinceService.GetStateProvinceById(stateProvince.ParentId); } return result; } } }
第五步:更改视图_CreateOrUpdate.cshtml 和 _CreateOrUpdateState.cshtml
1._CreateOrUpdate.cshtml 修改如下(蓝色标记):
<table class="adminContent"> <tr> <td> @(Html.Telerik().Grid<StateProvinceModel>() .Name("states-grid") .DataKeys(x => { x.Add(y => y.Id).RouteKey("Id"); }) .Columns(columns => { //columns.Bound(x => x.Name).Width(250); //面包屑呈现 columns.Bound(x => x.Breadcrumb).Title(T("Admin.Configuration.Countries.States.Fields.Name").Text).Width(250); //TODO display localized values here columns.Bound(x => x.Abbreviation).Width(100); columns.Bound(x => x.Published) .Width(100) .Template(x => x.Published.ToString().ToLower()) .Centered(); columns.Bound(x => x.DisplayOrder1).Width(100); columns.Bound(x => x.Id) .Width(50) .Centered() .ClientTemplate("<input type='submit' value='" + @T("Admin.Common.Edit").Text + "' onclick=\"" + "javascript:OpenWindow('" + @Url.Content("~/Admin/Country/StateEditPopup/") + "<#= Id #>?btnId=btnRefresh&formId=country-form', 800, 350, true); return false;\" class='t-button' />") .Title(T("Admin.Common.Edit").Text); columns.Command(commands => { commands.Delete(); }).Width(50); }) .DataBinding(dataBinding => { dataBinding.Ajax().Select("States", "Country", new { countryId = Model.Id }) .Delete("StateDelete", "Country"); }) .ClientEvents(x => x.OnError("grid_onError")) .EnableCustomBinding(true)) </td> </tr> <tr> <td width="100%"> <input type="submit" id="btnAddNewState" name="btnAddNewState" value="@T("Admin.Configuration.Countries.States.AddNew")" onclick="javascript:OpenWindow('@(Url.Action("StateCreatePopup", "Country", new { countryId = Model.Id, btnId = "btnRefresh", formId = "country-form" }))', 800, 300, true); return false;" class="t-button" /> <input type="submit" id="btnRefresh" name="btnRefresh" style="display: none" /> <script type="text/javascript"> $(document).ready(function () { $('#btnRefresh').click(function () { //refresh grid var optionsGrid = $("#states-grid"); optionsGrid.data('tGrid').ajaxRequest(); //return false to don't reload a page return false; }); }); </script> </td> </tr> </table>
2._CreateOrUpdateState.cshtml 修改如下(蓝色标记)增加表单项:
<table class="adminContent"> <tr> <td class="adminTitle"> @Html.NopLabelFor(model => model.ParentId): </td> <td class="adminData"> <!--父级类别--> @{ //[email protected] 2012年8月2日16:48:34 //var parentProvinces = new List<DropDownItem> { new DropDownItem { Text = "[None]", Value = "0" } }; //http://localhost/Admin/Country/AllProvinces?selectedId=0 } @(Html.Telerik() .ComboBoxFor(x => x.ParentId) .BindTo(Model.ParentProvinces) .Encode(true) .DataBinding(x => x.Ajax().Enabled(true).Select("AllProvinces", "Country", new { selectedId = Model.CountryId }))) @Html.ValidationMessageFor(model => model.ParentId) </td> </tr> <tr> <td class="adminTitle"> @Html.NopLabelFor(model => model.Abbreviation): </td> <td class="adminData"> @Html.EditorFor(model => model.Abbreviation) @Html.ValidationMessageFor(model => model.Abbreviation) </td> </tr> <tr> <td class="adminTitle"> @Html.NopLabelFor(model => model.Published): </td> <td class="adminData"> @Html.EditorFor(model => model.Published) @Html.ValidationMessageFor(model => model.Published) </td> </tr> <tr> <td class="adminTitle"> @Html.NopLabelFor(model => model.DisplayOrder1): </td> <td class="adminData"> @Html.EditorFor(model => model.DisplayOrder1) @Html.ValidationMessageFor(model => model.DisplayOrder1) </td> </tr> </table>
第六步:在Nop.Admin.Controllers 中增加控制方法 AllProvinces()代码如下:
//[email protected] 2012年8月2日16:51:35 //获取全部省份 public ActionResult AllProvinces(string text, int selectedId) { //StateProvince var province = _stateProvinceService.GetStateProvincesByCountryId(selectedId, true); province.Insert(0, new StateProvince { Name = "[None]", Id = 0 }); var selectList = new List<SelectListItem>(); foreach (var c in province) selectList.Add(new SelectListItem() { Value = c.Id.ToString(), Text = c.GetStateProvinceBreadCrumb(_stateProvinceService), Selected = c.Id == selectedId }); return new JsonResult { Data = selectList, JsonRequestBehavior = JsonRequestBehavior.AllowGet }; }
第七步:分别更改方法如下:
1. 方法 States(int countryId, GridCommand command)
[HttpPost, GridAction(EnableCustomBinding = true)] public ActionResult States(int countryId, GridCommand command) { if (!_permissionService.Authorize(StandardPermissionProvider.ManageCountries)) return AccessDeniedView(); var states = _stateProvinceService.GetStateProvincesByCountryId(countryId, true) .Select(x => { var vmodel = x.ToModel(); vmodel.Breadcrumb = x.GetStateProvinceBreadCrumb(_stateProvinceService); return vmodel; }); var model = new GridModel<StateProvinceModel> { Data = states, Total = states.Count() }; return new JsonResult { Data = model }; }
2. 方法StateCreatePopup(int countryId)
public ActionResult StateCreatePopup(int countryId) { if (!_permissionService.Authorize(StandardPermissionProvider.ManageCountries)) return AccessDeniedView(); var model = new StateProvinceModel(); model.CountryId = countryId; //[email protected] 2012年8月2日16:52:57 //--> model.ParentId = 0; model.ParentProvinces = new List<DropDownItem> { new DropDownItem { Text = "[None]", Value = "0" } }; //<-- //locales AddLocales(_languageService, model.Locales); return View(model); }
3.方法StateCreatePopup(string btnId, string formId, StateProvinceModel model)
[HttpPost] public ActionResult StateCreatePopup(string btnId, string formId, StateProvinceModel model) { if (!_permissionService.Authorize(StandardPermissionProvider.ManageCountries)) return AccessDeniedView(); var country = _countryService.GetCountryById(model.CountryId); if (country == null) //No country found with the specified id return RedirectToAction("List"); //[email protected] 2012年8月2日16:54:43 //父级省份提供 //防止提交后 "dataSource" cannot be null.错误 //Text = parentCategory.GetCategoryBreadCrumb(_categoryService), Value = parentCategory.Id.ToString() //--> model.ParentProvinces = new List<DropDownItem> { new DropDownItem { Text = "[None]", Value = "0" } }; if (model.ParentId >= 0) { var parentProvinces = _stateProvinceService.GetStateProvinceById(model.ParentId); if (parentProvinces != null) model.ParentProvinces.Add(new DropDownItem { Text = parentProvinces.GetStateProvinceBreadCrumb(_stateProvinceService), Value = parentProvinces.Id.ToString() }); else model.ParentId = 0; } //<-- if (ModelState.IsValid) { var sp = model.ToEntity(); _stateProvinceService.InsertStateProvince(sp); UpdateLocales(sp, model); ViewBag.RefreshPage = true; ViewBag.btnId = btnId; ViewBag.formId = formId; return View(model); } //If we got this far, something failed, redisplay form return View(model); }
4.方法StateEditPopup(int id)
//edit public ActionResult StateEditPopup(int id) { if (!_permissionService.Authorize(StandardPermissionProvider.ManageCountries)) return AccessDeniedView(); var sp = _stateProvinceService.GetStateProvinceById(id); if (sp == null) //No state found with the specified id return RedirectToAction("List"); var model = sp.ToModel(); //[email protected] 2012年8月2日16:55:50 //--> model.ParentProvinces = new List<DropDownItem> { new DropDownItem { Text = "[None]", Value = "0" } }; if (model.ParentId > 0) { var parentProvinces = _stateProvinceService.GetStateProvinceById(model.ParentId); if (parentProvinces != null) model.ParentProvinces.Add(new DropDownItem { Text = parentProvinces.GetStateProvinceBreadCrumb(_stateProvinceService), Value = parentProvinces.Id.ToString() }); else model.ParentId = 0; } //<-- //locales AddLocales(_languageService, model.Locales, (locale, languageId) => { locale.Name = sp.GetLocalized(x => x.Name, languageId, false, false); }); return View(model); }
5.方法StateEditPopup(string btnId, string formId, StateProvinceModel model)
[HttpPost] public ActionResult StateEditPopup(string btnId, string formId, StateProvinceModel model) { if (!_permissionService.Authorize(StandardPermissionProvider.ManageCountries)) return AccessDeniedView(); var sp = _stateProvinceService.GetStateProvinceById(model.Id); if (sp == null) //No state found with the specified id return RedirectToAction("List"); //[email protected] 2012年8月2日16:57:12 //防止提交后 "dataSource" cannot be null.错误 //--> model.ParentProvinces = new List<DropDownItem> { new DropDownItem { Text = "[None]", Value = "0" } }; //<-- if (ModelState.IsValid) { sp = model.ToEntity(sp); _stateProvinceService.UpdateStateProvince(sp); UpdateLocales(sp, model); ViewBag.RefreshPage = true; ViewBag.btnId = btnId; ViewBag.formId = formId; return View(model); } //If we got this far, something failed, redisplay form return View(model); }
最后让我们来预览下最终改造后的结果:
如下图
就这样很灵活变通的形式就实现了符合中国国家区域划分的管理方式~
http://www.cnblogs.com/mschen/articles/Nopcommerce.html