导读:
代码可以在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需要用到的数据了,想一想,它需要哪些东东呢?可以先看下代码,稍有点复杂,不要急,后面再做逐步的分析,下面是代码:
1
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的呈现逻辑:
1
<%
@ Control Language
=
"
C#
"
Inherits
=
"
System.Web.Mvc.ViewUserControl<Chinasoft.Models.DdlFormModel>
"
%>
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里:
1
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,所以用了些俗称硬编码的东东,嘿嘿:
其中定义如下接口:
1
2
public
interface
IDdlSampleRepository
3
{
4
DdlSampleFormModel GetInfo();
5
}
然后具体类:
1
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):
1
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当然是对地址的一个封装,代码如下:
1
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,第二个是添加空选项:
1
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
}
欢迎扔鸡蛋!