导读:
代码可以在http://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 }
欢迎扔鸡蛋!