MVC地区多级联动扩展实现(非递归形式)

MVC前台界面调用方式如下:

 @Html.AreaDropDownList("areaCode", areaCode, 3, string.Empty)

参数说明:

第一个参数控件的名称;
 第二个参数选中的地区编码;
 第三个参数地区层级;
 第四个参数根级地区;

地区数据库表设计如下:

下拉列表的扩展:

 1   #region 下拉列表
 2
 3         /// <summary>
 4         /// 联动下拉列表
 5         /// </summary>
 6         /// <param name="htmlHelper">被扩展的HtmlHelper实例</param>
 7         /// <param name="expression">获取数据集合</param>
 8         /// <param name="level">显示多少级</param>
 9         /// <param name="defaultValue">TProperty类型的默认值(如string默认值为"")</param>
10         /// <param name="rootItems">获取根级列表数据</param>
11         /// <param name="getParentID">获取列表项的ParentID方法</param>
12         /// <param name="getChildItems">获取子级列表数据集合方法</param>
13         /// <param name="getChildSelectDataUrl">获取子级列表数据的远程地址</param>
14         /// <returns>html代码</returns>
15         public static MvcHtmlString LinkageDropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, TProperty defaultValue, int level, Dictionary<TProperty, string> rootItems,Func<TProperty, TProperty> getParentID, Func<TProperty, Dictionary<TProperty, string>> getChildItems,string getChildSelectDataUrl,string optionLabel = "请选择")
16         {
17             ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
18
19             return LinkageDropDownList(htmlHelper, ExpressionHelper.GetExpressionText(expression), (TProperty)metadata.Model, defaultValue, level, rootItems, getParentID,getChildItems,getChildSelectDataUrl,optionLabel);
20         }
21
22
23         /// <summary>
24         /// 联动下拉列表
25         /// </summary>
26         /// <param name="htmlHelper">被扩展的HtmlHelper实例</param>
27         /// <param name="level">显示多少级</param>
28         /// <param name="defaultValue">TProperty类型的默认值(如string默认值为"")</param>
29         /// <param name="name">下拉列表表单项名</param>
30         /// <param name="selectedValue">当前选中值</param>
31         /// <param name="rootItems">获取根级列表数据</param>
32         /// <param name="getParentId">获取列表项的ParentID方法</param>
33         /// <param name="getChildItems">获取子级列表数据集合方法</param>
34         /// <param name="getChildSelectDataUrl">获取子级列表数据的远程地址</param>
35         /// <returns>html代码</returns>
36         public static MvcHtmlString LinkageDropDownList<TProperty>(this HtmlHelper htmlHelper, string name, TProperty selectedValue,TProperty defaultValue, int level, Dictionary<TProperty, string> rootItems, Func<TProperty, TProperty> getParentId, Func<TProperty, Dictionary<TProperty, string>> getChildItems, string getChildSelectDataUrl, string optionLabel = "请选择")
37         {
38             string fullName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
39             //select data init
40             Stack<Dictionary<TProperty, string>> stack = new Stack<Dictionary<TProperty, string>>();
41
42             //如果有选中的值,则查找其所在列表前面的所有列表
43             IList<TProperty> selectedValues = new List<TProperty>();
44             if (selectedValue != null && !selectedValue.Equals(defaultValue))
45             {
46                 TProperty itemId = selectedValue;
47                 TProperty parentItemId = getParentId(itemId);
48                 while (!itemId.Equals(defaultValue) && !parentItemId.Equals(defaultValue))
49                 {
50                     stack.Push(getChildItems(parentItemId));
51                     selectedValues.Add(itemId);
52                     itemId = parentItemId;
53                     parentItemId = getParentId(itemId);
54                 }
55                 if (rootItems.Count() > 0)
56                 {
57                     TProperty rootId = getParentId(rootItems.First().Key);
58                     if (!itemId.Equals(rootId))
59                     {
60                         stack.Push(rootItems);
61                         selectedValues.Add(itemId);
62                     }
63                 }
64             }
65             else
66             {
67                 TProperty rootItemID = rootItems.Select(n => n.Key).FirstOrDefault();
68                 stack.Push(rootItems);
69             }
70
71             //生成标签
72             TagBuilder containerBuilder = new TagBuilder("span");
73             containerBuilder.MergeAttribute("plugin", "linkageDropDownList");
74             var data = new Dictionary<string, object>();
75             data.TryAdd("GetChildSelectDataUrl", getChildSelectDataUrl);
76             data.TryAdd("ControlName", name);
77             data.TryAdd("Level", level);
78             data.TryAdd("OptionLabel", optionLabel);
79             data.TryAdd("DefaultValue", defaultValue.ToString());
80             containerBuilder.MergeAttribute("data", Json.Encode(data));
81             int currentIndex = 0;
82             while (stack.Count > 0)
83             {
84                 Dictionary<TProperty, string> dictionary = stack.Pop();
85                 IEnumerable<SelectListItem> selectList = dictionary.Select(n => new SelectListItem() { Selected = selectedValues.Contains(n.Key), Text = n.Value, Value = n.Key.ToString() });
86                 containerBuilder.InnerHtml += "\r\n" + htmlHelper.DropDownList(string.Format("{0}_{1}", name, currentIndex), selectList,
87                                 optionLabel, new { @class = "tn-dropdownlist" });
88                 currentIndex++;
89             }
90             containerBuilder.InnerHtml += "\r\n" + htmlHelper.Hidden(name);
91             return MvcHtmlString.Create(containerBuilder.ToString());
92         }
93
94         #endregion

对外的调用的实现:

 1         /// <summary>
 2         /// 地区下拉列表
 3         /// </summary>
 4         /// <param name="htmlHelper">被扩展的htmlHelper实例</param>
 5         /// <param name="expression">选择实体中类别属性的lamda表达式</param>
 6         /// <param name="areaLevel">地区层级(默认取站点地区配置)</param>
 7         /// <param name="rootAreaCode">根级地区(默认取站点地区配置)</param>
 8         public static MvcHtmlString AreaDropDownListFor<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, string>> expression, int? areaLevel = null, string rootAreaCode = null)
11         {
12             string getChildAreasUrl = "/Channel/GetChildAreas";//获取子地区的远程地址,(AreaCode,name)的JSON数据
13             if (areaLevel == null)
15             {
16                 areaLevel = 0;//区域设置级别,可以作为配置文件获取
17             }
18             return htmlHelper.LinkageDropDownListFor<TModel, string>(expression, string.Empty, areaLevel.Value, 获取根级区域的(AreaCode,name)键值对,获取当前选中区域的父区域, 获取当前的子区域, getChildAreasUrl);
21         }
22
23         /// <summary>
24         /// 地区下拉列表
25         /// </summary>
26         /// <param name="htmlHelper">被扩展的htmlHelper实例</param>
27         /// <param name="name">控件name属性</param>
28         /// <param name="name">选中的地区编码</param>
29         /// <param name="areaLevel">地区层级(默认取站点配置)</param>
30         /// <param name="rootAreaCode">根级地区(默认取站点地区配置)</param>
31         public static MvcHtmlString AreaDropDownList(this HtmlHelper htmlHelper, string name, string value, int? areaLevel = null, string rootAreaCode = null)
32         {
33              string getChildAreasUrl = "/Channel/GetChildAreas";//获取子地区的远程地址,(AreaCode,name)的JSON数据
34             if (areaLevel == null)
36             {
37                 areaLevel = 0;//区域设置级别,可以作为配置文件获取
38             }
39             return htmlHelper.LinkageDropDownList<string>(name, value, string.Empty, areaLevel.Value, 获取根级区域的(AreaCode,name)键值对, 获取当前选中区域的父区域, 获取选中地区当前的子区域, getChildAreasUrl);
42         }
时间: 2024-11-23 04:53:43

MVC地区多级联动扩展实现(非递归形式)的相关文章

算法:归并算法的递归与非递归形式

归并算法是将两个或两个以上的有序表组合成一个新的有序表,它的原理是:假设初始序列含有n个记录,则可以看成是n个有序子序列,两两归并,得到[n/2]个有序子序列,再次归并--不断重复直至归并到长度为n的有序序列,这样的排序方法称为2路归并排序. 实例一:递归形式的2路归并算法 #define MAXSIZE 4 int data[MAXSIZE] = {2,1,0,3}; /* * 功能:将from数组min到max-1下标数据排好序,最后的结果是to[min]...to[max-1] * 输入:

[一个算法] 快速排序的非递归形式实现

fast sort如何实现? 在实际的递归算法当中,我们我们使用一个pivot将数组分为了两部分,然后在分别递归处理这两部分,使用递归先处理左半部分,然后是右半部分,这是用递归可以很容易实现. 但是使用递归的坏处是可能会溢出,当然对于比较良好的分布,即在每一步都能讲数组评分的情况,栈溢出的可能性很小,但是如果不是这种情况,那么就可能会递归很多层,那么这种情况下,算法很容易溢出. 因此将这个算法改为非递归的实现方式,还是非常有意义的.那么问题来了,如何实现非递归的算法? 仔细想想这个算法的过程,会

二叉树总结—建树和4种遍历方式(递归&amp;&amp;非递归)

今天总结一下二叉树,要考离散了,求不挂!二叉树最重要的就是 建立.4种遍历方式,简单应用,如何判断两颗二叉树是否相似 二叉树分为 :1.完全二叉树  2.满二叉树 结构性质: 1).满二叉树 高度为h ,节点数则为 2^h - 1,且叶子节点全在最下层,且叶子节点数为2^(n-1)个{n代表二叉树层数,也叫深度} 2).n个节点的 完全二叉树 深度为 int(log2n)(以2为底n的对数)+ 1: 3).非空二叉树 叶子节点个数==双分支节点数+1 4).非空二叉树 某节点编号 n  若有左孩

[一个算法] 图DFS非递归实现

图的遍历方式当中DFS和BFS是两种主要的遍历方式.DFS主要是使用递归思想来实现的,BFS主要是使用队列来保存下面的节点.BFS的一个优势是不是非递归形式,所以栈溢出的可能性很小,相反DFS在这方面的限制比较大.因此,如何将DFS改为非递归形式意义重大. 如何将DFS变为非递归形式呢? 实际上,前面带了一个很大的帽子,对于DFS的非递归实现并不是非常的困难. 我们将访问到的节点因此放入到一个栈当中,并且标记这个节点为访问过,如果这个节点有孩子,判断其孩子还有被访问的情况下,将其一次亚茹栈当中.

斐波那契序列的递归和非递归的实现

  斐波那契数列(Fibonacci sequence),又称黄金分割数列.因数学家列昂纳多·斐波那契(Leonardoda Fibonacci[1])以兔子繁殖为例子而引入,故又称为"兔子数列".   指的是这样一个数列:0.1.1.2.3.5.8.13.21.34.--在数学上,斐波纳契数列以如下被以递归的方法定义:         F(0)=0,F(1)=1,F(n)=F(n-1)+F(n-2)(n≥2,n∈N*)       #include<iostream> u

归并排序-非递归应用

/** function:     合并2个有序数组,有效到大     input:     数组first pData[begin..mid]     数组second pData[mid+1..end]     output:pData[begin...end]          需要空间:o(n) **/ void merge(int *pData,int begin,int mid,int end) {     int pTemp[8]={0};     int first =begin

二叉树序言、为了、经过非递归措辞预订透彻的分析

前言 前两篇文章二叉树和二叉搜索树中已经涉及到了二叉树的三种遍历.递归写法,仅仅要理解思想,几行代码.但是非递归写法却非常不easy.这里特地总结下,透彻解析它们的非递归写法.当中.中序遍历的非递归写法最简单,后序遍历最难.我们的讨论基础是这种: //Binary Tree Node typedef struct node { int data; struct node* lchild; //左孩子 struct node* rchild; //右孩子 }BTNode; 首先.有一点是明白的:非

二叉树前序、中序、后序遍历非递归写法的透彻解析

前言 在前两篇文章二叉树和二叉搜索树中已经涉及到了二叉树的三种遍历.递归写法,只要理解思想,几行代码.可是非递归写法却很不容易.这里特地总结下,透彻解析它们的非递归写法.其中,中序遍历的非递归写法最简单,后序遍历最难.我们的讨论基础是这样的: //Binary Tree Node typedef struct node { int data; struct node* lchild; //左孩子 struct node* rchild; //右孩子 }BTNode; 首先,有一点是明确的:非递归

组合问题非递归

组合问题非递归形式: 例如有5个数,选其中3个数 ,将其模拟成 1 1 1 0 0 1 1 0 1 0 1 1 0 0 1 1 0 1 1 0 1 0 0 1 1 0 1 1 1 0 .......... 需要将每次交换后的1结合在一起. 1 #include<cstdio> 2 int b[25]={ 3 0 4 } ; 5 void Print(int len,int r) 6 { 7 int temp=0; 8 for(int i=0;i<len;i++) 9 { 10 if(b[