导读:
代码可以在https://files.cnblogs.com/bighuiwolf/Chinasoft.rar下载。
第一篇:http://www.cnblogs.com/bighuiwolf/archive/2010/07/10/1774871.html
第二篇:http://www.cnblogs.com/bighuiwolf/archive/2010/07/10/1774920.html
第三篇:http://www.cnblogs.com/bighuiwolf/archive/2010/07/10/1774955.html
本篇为第二篇
该说FormModel了,最核心的就是DropDownList需要用到的数据了,想一想,它需要哪些东东呢?可以先看下代码,稍有点复杂,不要急,后面再做逐步的分析,下面是代码:
2 public class DdlFormModel
3 {
4 public DdlFormModel()
5 {
6 }
7
8 public DdlFormModel(string ddlKeyConfig, string ddlName, SelectList ddlData)
9 {
10 DdlKeyConfig = ddlKeyConfig;
11 DdlName = ddlName;
12 DdlData = ddlData;
13 }
14
15 public string DdlKeyConfig { get; set; }
16 public string DdlName { get; set; }
17 public SelectList DdlData { get; set; }
18 private string _onchange;
19 public object HtmlAttributes
20 {
21 get
22 {
23 if (!string.IsNullOrEmpty(_onchange))
24 return new { onchange = _onchange };
25 return null;
26 }
27 }
28
29 public void SetChilds(string childIds, string childKey)
30 {
31 if (childIds != null && childIds.Length > 0)
32 {
33 string[] childIdArray = childIds.Split(',');
34 string subChildIds = null;
35 int idx = childIds.IndexOf(",");
36 if (idx > -1)
37 subChildIds = childIds.Substring(idx + 1);
38
39 StringBuilder sb = new StringBuilder();
40 for (int i = 1; i < childIdArray.Length; i++)
41 {
42 sb.AppendFormat("ClearChilds('{0}');", childIdArray[i]);
43 }
44 sb.AppendFormat("GetChilds(this.id, '{0}', '{1}', '{2}', '{3}');"
45 ,DdlKeyConfig, childIdArray[0], childKey, subChildIds);
46
47 if (_onchange == null)
48 {
49 _onchange = sb.ToString();
50 }
51 else
52 {
53 _onchange += sb.ToString();
54 }
55 }
56 }
57
58 public static DdlFormModel CreateInstance(
59 string ddlKeyConfig
60 , string ddlName
61 , IHasParent hasParent
62 , int parentId
63 , int? selectedValue
64 , string childIds
65 , string childKey)
66 {
67 SelectList selectList = hasParent.GetSelectListByParentId(parentId, selectedValue);
68 var instance = new DdlFormModel(ddlKeyConfig, ddlName, selectList);
69 if (!string.IsNullOrEmpty(childIds))
70 {
71 instance.SetChilds(childIds, childKey);
72 }
73 return instance;
74 }
75
76 public static DdlFormModel CreateInstance(
77 string ddlKeyConfig
78 , string ddlName
79 , IHasParent hasParent
80 , int parentId
81 , int? selectedValue)
82 {
83 return CreateInstance(ddlKeyConfig, ddlName, hasParent, parentId, selectedValue, null, null);
84 }
85
86 public static DdlFormModel CreateInstance(
87 string ddlKeyConfig
88 , string ddlName
89 , SelectList selectList
90 , string childIds
91 , string childKey)
92 {
93 var instance = new DdlFormModel(ddlKeyConfig, ddlName, selectList);
94 if (!string.IsNullOrEmpty(childIds))
95 {
96 instance.SetChilds(childIds, childKey);
97 }
98 return instance;
99 }
100 }
FormModel跟View要一块儿看才清楚,我定义了以下PartialView即用户控件来作为DropDownList的呈现逻辑:
2 <% if (Model != null)
3 { %>
4 <%= Html.DropDownList(Model.DdlName, Model.DdlData, Model.HtmlAttributes)%>
5 <% }
6 else
7 { %>
8 Model为空
9 <% } %>|<%= DateTime.Now %>
可以看到,里面用到了DdlFormModel的DdlName, DdlData, HtmlAttributes三个属性。它的构造函数里有三个参数(string ddlKeyConfig, string ddlName, SelectList ddlData),可能后两个参数大家能看明白,ddlName就是控件名,ddlData就是从SelectListProviderBase(顶级)或IHasParent(子级)获取到的数据。而ddlKeyConfig不容易看明白,它与配置文件有关,我们都知道级连的东西要定义一个级连的顺序,我把这个顺序定义在了web.config里:
2 <appSettings>
3 <add key="Ddl_Keys_Address" value="Ddl_City,Ddl_Suburb,Ddl_Street"/>
4 <add key="Ddl_City" value="Chinasoft.Models.Cities"/>
5 <add key="Ddl_Suburb" value="Chinasoft.Models.Suburbs"/>
6 <add key="Ddl_Street" value="Chinasoft.Models.Streets"/>
7 </appSettings>
进一步看为Form获取数据的代码会更明白一点,以下是后面例子(本系列第三篇)中要调用的为View提供数据的代码(DdlSampleFormModel的定义稍后贴出),因为是Demo,所以用了些俗称硬编码的东东,嘿嘿:
其中定义如下接口:
2 public interface IDdlSampleRepository
3 {
4 DdlSampleFormModel GetInfo();
5 }
然后具体类:
2 public class DdlSampleRepository : IDdlSampleRepository
3 {
4 public DdlSampleFormModel GetInfo()
5 {
6 DdlSampleFormModel model = new DdlSampleFormModel();
7 model.Data = new AddressDetailModel(0, 0, 0, 0, "Other info");
8
9 var ddlKeyConfig = "Ddl_Keys_Address";
10
11 var countrySelectList = new Countries().GetSelectList(model.Data.Country);
12 model.Countries = DdlFormModel.CreateInstance(
13 ddlKeyConfig
14 , "County"
15 , countrySelectList
16 , "City,Suburb,Street"
17 , "Ddl_City");
18
19 model.Cities = DdlFormModel.CreateInstance(
20 ddlKeyConfig
21 , "City"
22 , new Cities()
23 , model.Data.Country
24 , model.Data.City
25 , "Suburb,Street"
26 , "Ddl_Suburb");
27
28 model.Suburbs = DdlFormModel.CreateInstance(
29 ddlKeyConfig
30 , "Suburb"
31 , new Suburbs()
32 , model.Data.City
33 , model.Data.Suburb
34 , "Street"
35 , "Ddl_Street");
36
37 model.Streets = DdlFormModel.CreateInstance(
38 ddlKeyConfig
39 , "Street"
40 , new Streets()
41 , model.Data.Suburb
42 , model.Data.Street);
43
44 return model;
45 }
46 }
其中的var ddlKeyConfig = "Ddl_Keys_Address";对应配置文件中的第一个配置的key,它定义了层次顺序,同时也可以看出来DdlFormModel的第三个CreateInstance方法重载是用于顶级下拉框的(这里用于国家),第一个CreateInstance方法重载是用于既有父又有子的下拉框的(这里是城市、区县),第二个CreateInstance方法重载是用于底层下拉框的(这里是Street)。
配置文件里的第二、三、四个配置,是用于利用反射来获取下拉框后续数据的,简单说就是当国家变了时候用Ajax来更新城市、区县、街道时候用的。具体在第三篇里讨论。
下面是DdlSampleFormModel的代码(它用于Views\DdlSample\Index.aspx提供数据,在第三篇可以看到Views\DdlSample\Index.aspx):
2 public class DdlSampleFormModel
3 {
4 public AddressDetailModel Data { get; set; }
5 public DdlFormModel Countries { get; set; }
6 public DdlFormModel Cities { get; set; }
7 public DdlFormModel Suburbs { get; set; }
8 public DdlFormModel Streets { get; set; }
9 }
后四个参数类型在本文的开始已经贴过了,是为下拉框用户控件提供的数据。第一个参数Data当然是对地址的一个封装,代码如下:
2 public class AddressDetailModel
3 {
4 public int Country { get; set; }
5 public int City { get; set; }
6 public int Suburb { get; set; }
7 public int Street { get; set; }
8 public string OtherInfo { get; set; }
9
10 public AddressDetailModel()
11 {
12 }
13 public AddressDetailModel(int country, int city, int suburb, int street, string otherInfo)
14 {
15 Country = country;
16 City = city;
17 Suburb = suburb;
18 Street = street;
19 OtherInfo = otherInfo;
20 }
21 }
题目虽为FormModel们,但是光看Model不容易看明白,所以把有关上下文的代码都贴了上来,以帮助理解。细心的人应该会注意到DdlFormModel类里一定也用到Javascript了吧,JS代码会在第三篇里贴出。
忘了有一个工具类了,它是在HasParentBase和SelectListProviderBase中使用到的,一共2个功能,第一个功能是根据基础数据生成SelectList,第二个是添加空选项:
2 public static class RepositoryHelper
3 {
4 public static SelectList GetSelectList
5 (IEnumerable<KeyValuePair<string, string>> values, int? selectedValue)
6 {
7 SelectList list;
8 if (selectedValue.HasValue)
9 {
10 list = new SelectList(values, "Key", "Value", selectedValue);
11 }
12 else
13 {
14 list = new SelectList(values, "Key", "Value");
15 }
16 return list;
17 }
18
19 public static void AddEmpty(List<KeyValuePair<string, string>> list)
20 {
21 list.Insert(0, new KeyValuePair<string, string>("", ""));
22 }
23 }
欢迎扔鸡蛋!