导读:
代码可以在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
本篇为第三篇
好,现在可以看全貌了,程序清单先列出来:
- 配置
- 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,代码已经贴完了,欢迎大侠们指点!