导读:
代码可以在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
本篇为第三篇
好,现在可以看全貌了,程序清单先列出来:
- 配置
- Web.config —————— 下拉框配置
- Global.asax —————— 通用下拉框显示路由
- Model
- AddressDetailModel.cs —————— 地址Model
- Countries.cs —————— 国家
- Cities.cs —————— 城市
- Suburbs.cs —————— 区
- Streets.cs —————— 街道
- Form Model
- DdlSampleFormModel.cs —————— 供Demo页面使用的Model
- DdlFormModel.cs —————— 供GetDdl.ascx使用的Model
- View
- /Views/DdlSample/Index.aspx —————— Demo页面
- /Views/Shared/GetDdl.ascx —————— 通用下拉框显示控件
- Controller
- DdlSampleController.cs —————— Demo页面Controller
- DdlController.cs —————— 通用下拉框响应Controller
- Others
- IDdlSampleRepository.cs —————— 业务逻辑接口
- DdlSampleRepository.cs —————— 业务逻辑实现
- IHasParent.cs —————— 有父亲的下拉框接口
- HasParentBase.cs —————— 有父亲的下拉框基类
- RepositoryHelper.cs —————— 工具类
- ISelectListProvider.cs —————— 可提供下拉框数据的接口
- SelectListProviderBase.cs —————— 可提供下拉框数据的基类
首先要定义一个URL路由来作为Demo中PartialView即通用下拉框显示用户控件的访问地址,View的地址可以由默认代码实现:
2 public static void RegisterRoutes(RouteCollection routes)
3 {
4 routes.IgnoreRoute( " {resource}.axd/{*pathInfo} " );
5
6 routes.IgnoreRoute( " {*favicon} " , new { favicon = @" (.*/)?favicon.ico(/.*)? " });
7
8 // Ddl/Ddl_Keys_Address/1/City/Ddl_City/Suburb,Street
9 routes.MapRoute(
10 " Ddl "
11 , " Ddl/{DdlKeyConfig}/{parentId}/{ddlName}/{key}/{childIds} "
12 , new { controller = " Ddl " , action = " Index " , childIds = "" }
13 );
14
15 // CacheTest
16 routes.MapRoute(
17 " CacheTest "
18 , " CacheTest "
19 , new { controller = " Ddl " , action = " CacheTest " }
20 );
21
22 routes.MapRoute(
23 " Default " , // Route name
24 " {controller}/{action}/{id} " , // URL with parameters
25 new { controller = " Home " , action = " Index " , id = "" } // Parameter defaults
26 );
27
28 }
第9行的那个路由就是为用户控件准备的,第8行的例子表示,当选择了国家下拉框(Value为1)后,Ajax所请求的Url,返回的当然是一段Html,而这些会更新页面上的局部显示。还是先把JS代码列出来吧(文件名为commonddl.js):
2 var parentId = $( " # " + parentDdlId).val();
3 if (parentId != "" ) {
4 var wrapper = $( " # " + ddlName + " Wrapper " );
5 wrapper.html( " <img src='/Content/images/loading.gif' /> " );
6 var url = " /Ddl/ " + ddlKeyConfig + " / " + parentId + " / " + ddlName + " / " + key;
7 if (childIds != null && childIds != "" ) {
8 url += " / " + childIds;
9 }
10 nsDebug.addMsgLine(url);
11 $. get (url, function(result) { wrapper.html(result); }, " text " );
12 }
13 else {
14 ClearChilds(ddlName);
15 }
16 }
17 function ClearChilds(ddlName) {
18 document.getElementById(ddlName).options.length = 0 ;
19 }
20 function CacheTest(url) {
21 $. get (url, function(result) { alert(result); }, " text " );
22 }
这也就是第二篇中最先讲到的类DdlFormModel中调用的代码。提示:本JS以JQuery为基础,所以页面上需要先引入JQuery。nsDebug您可以忽略,它是我调试代码用的,可以在页面上输出一些我需要观察的信息。所幸贴出来吧(文件名为Debug.js):
2 var nsDebug = {};
3 nsDebug.rowNumber = 0 ;
4 nsDebug.getMsgDiv = function() {
5 if ($( " #divMsg " ).length == 0 ) {
6 // $("body").append($("<div id='divMsg'></div>"));
7 $( " <div id='divMsg' style='background-color: yellow'></div> " ).appendTo( " body " );
8 }
9 return $( " #divMsg " );
10 };
11 nsDebug.addMsgLine = function(msg) {
12 nsDebug.rowNumber ++ ;
13 nsDebug.getMsgDiv().append(nsDebug.rowNumber + " . " + msg).append( " <br /> " );
14 };
下面是用来响应Ajax请求返回下拉框Html代码的Controler(名为Controllers\DdlController.cs):
2 public class DdlController : Controller
3 {
4 // 对于PartialView,默认是不缓存的
5 // 对于View,默认是缓存的
6 // 本方法返回PartialView,这里的数据是恒定不变的,要缓存是合适的,所以要显式的设置缓存,以下设置为100分钟
7 [OutputCache(Duration = 100 * 60 , Location = OutputCacheLocation.ServerAndClient, VaryByParam = " * " )]
8 // 禁用缓存的代码是:[OutputCache(Duration = -1, Location = OutputCacheLocation.None)]
9 public ActionResult Index(
10 string DdlKeyConfig
11 , int parentId
12 , string ddlName, string key
13 , string childIds)
14 {
15 Thread.Sleep( 500 );
16
17 string className = WebConfigurationManager.AppSettings[key];
18 IHasParent hasParent = Activator.CreateInstance(Type.GetType(className)) as IHasParent;
19 var selectList = hasParent.GetSelectListByParentId(parentId);
20
21 string childKey = null ;
22 if ( ! string .IsNullOrEmpty(childIds))
23 {
24 string Ddl_Keys = WebConfigurationManager.AppSettings[DdlKeyConfig];
25 var Ddl_Keys_Array = Ddl_Keys.Split( ' , ' );
26 for ( int i = 0 ; i < Ddl_Keys_Array.Length - 1 ; i ++ )
27 {
28 if (Ddl_Keys_Array[i] == key)
29 {
30 childKey = Ddl_Keys_Array[i + 1 ];
31 }
32 }
33 }
34
35 var ddlFormModel = DdlFormModel.CreateInstance(
36 DdlKeyConfig
37 , ddlName
38 , hasParent
39 , parentId
40 , null
41 , childIds
42 , childKey);
43
44 return PartialView( " GetDdl " , ddlFormModel);
45 }
46 public ActionResult CacheTest()
47 {
48 return View( " CacheTest " );
49 }
50 }
其中的Thread.Sleep(500);是模拟网络延迟的。
那个Views\Shared\GetDdl.ascx在第二篇已经贴过了,所以就不重复了。
下面主角登场,我们的示例Controller(名为Controllers\DdlSampleController.cs)和View(文件名为Views\DdlSample\Index.aspx):
2 public class DdlSampleController : Controller
3 {
4 public ActionResult Index()
5 {
6 IDdlSampleRepository ddlSampleRepository = new DdlSampleRepository();
7 return View(ddlSampleRepository.GetInfo());
8 }
9 }
-----------------------------
2
3 < asp:Content ID = " Content1 " ContentPlaceHolderID = " TitleContent " runat = " server " >
4 连动下拉框Demo
5 </ asp:Content >
6 < asp:Content ID = " Content2 " ContentPlaceHolderID = " MainContent " runat = " server " >
7
8 < script src = " http://www.cnblogs.com/Scripts/Debug.js " type = " text/javascript " ></ script >
9
10 < script type = " text/javascript " src = " http://www.cnblogs.com/Scripts/commonddl.js " ></ script >
11
12 < h2 >
13 连动下拉框Demo </ h2 >
14 < p >
15 < a href = " /DdlSample " > Demo </ a > | < a href = " /html/programlist.htm " > 程序清单 </ a > | < a href = " /html/democlass.htm " >
16 类图 </ a ></ p >
17 <%= Html.ValidationSummary( " Edit was unsuccessful. Please correct the errors and try again. " ) %>
18 <% using (Html.BeginForm())
19 { %>
20 < fieldset >
21 < legend > Fields </ legend >
22 < table >
23 < tr >
24 < th >
25 Country:
26 </ th >
27 < td >
28 <% Html.RenderPartial( " GetDdl " , Model.Countries); %>
29 </ td >
30 </ tr >
31 < tr >
32 < th >
33 City:
34 </ th >
35 < td id = " CityWrapper " >
36 <% Html.RenderPartial( " GetDdl " , Model.Cities); %>
37 </ td >
38 </ tr >
39 < tr >
40 < th >
41 Suburb:
42 </ th >
43 < td id = " SuburbWrapper " >
44 <% Html.RenderPartial( " GetDdl " , Model.Suburbs); %>
45 </ td >
46 </ tr >
47 < tr >
48 < th >
49 Street:
50 </ th >
51 < td id = " StreetWrapper " >
52 <% Html.RenderPartial( " GetDdl " , Model.Streets); %>
53 </ td >
54 </ tr >
55 < tr >
56 < th >
57 OtherInfo:
58 </ th >
59 < td >
60 <%= Model.Data.OtherInfo %>
61 </ td >
62 </ tr >
63 </ table >
64 < p >
65 < input type = " submit " value = " Save " />
66 < input type = " button " value = " 测缓存:取View " onclick = " CacheTest('/CacheTest'); " />
67 < input type = " button " value = " 测缓存:取PartialView " onclick = " CacheTest('/Ddl/Ddl_Keys_Address/1/City/Ddl_City/Suburb,Street'); " />
68 </ p >
69 </ fieldset >
70 <% } %>
71 </ asp:Content >
72
这个View实在是没啥讲头,值得注意的是有个缓存的问题,即View默认是被设计成缓存的,而PartialView默认是不缓存的,而我们在这里应该用缓存,所以您看到了稍前面刚贴出的代码里已经有说明了。
OK,代码已经贴完了,欢迎大侠们指点!