asp.net mvc下通用连动下拉框剖析(二)--FormModel们(最新完善版)

 

导读:

代码可以在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      }

 

 

欢迎扔鸡蛋!

posted on 2010-07-10 17:15 灰灰狼 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/bighuiwolf/archive/2010/07/10/1774920.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值