使用 AJAX 動態載入縣市和地區

在 Web 應用程式中,常常都需要提供可以讓使用者登錄個人資料(如姓名、聯絡電話、通訊地址)的互動式網頁。以地址輸入欄位來說,通常還會加入縣市及鄉鎮區的連動式下拉選單(Cascading Drop-Down)供使用者選擇。在 ASP.NET 中,傳統作法是使用兩個 DropDownList 控制項,並透過 AutoPostBack 的方式擷取選取項目,再動態將資料填入 DropDownList 控制項,來達到多層連動下拉選單的效果。不過,這樣的缺點是每次變更清單選取項目時,都會造成自動向伺服器發出網頁請求,增加網路傳輸量。所幸,你可以選擇 ASP.NET AJAX Control Toolkit 的 CascadingDropDown 控制項,來做為替代方案。

ASP.NET AJAX 已內建於 ASP.NET 3.5,所以只要下載 AJAX Control Toolkit 元件即可。如果是 ASP.NET 2.0 則必須先安裝 ASP.NET 2.0 AJAX Extensions 1.0,才可以使用 ASP.NET AJAX Control Toolkit。你可以造訪 ASP.NET AJAX 官方網站取得相關下載。

ASP.NET AJAX Control Toolkit 同時也提供了完整的範例程式碼,除了可以讓你快速學習外,也可以立即引用到你的 ASP.NET 開發專案。本文程式碼亦是以 CascadingDropDown 範例為基礎修改而來。接下來,將使用 ASP.NET 3.5 來說明如何使用 CascadingDropDown 控制項,並搭配 Web 服務來動態載入縣市及鄉鎮區資料項。

建立資料來源
在這裡我們使用 XML 文件來儲存縣市及鄉鎮區的資料,如以下所示:
<?xml version="1.0" encoding="utf-8" ?>
<PostCodeService>
<county name="台北市">
<town name="中正區" value="100"/>
<town name="大同區" value="103"/>
<town name="中山區" value="104"/>
<town name="松山區" value="105"/>
<town name="大安區" value="106"/>
<town name="萬華區" value="108"/>
<town name="信義區" value="110"/>
<town name="士林區" value="111"/>
<town name="北投區" value="112"/>
<town name="內湖區" value="114"/>
<town name="南港區" value="115"/>
<town name="文山區" value="116"/>
</county>
</PostCodeService>

建立 Web Service
為了讓 AJAX 用戶端指令碼能存取 Web 服務,我們必須建立 .asmx Web 服務,並且以 ScriptServiceAttribute 屬性限定 Web 服務類別。
using System;
using System.Collections.Specialized;
using System.Web;
using System.Web.Services;
using System.Xml;
using AjaxControlToolkit;

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.Web.Script.Services.ScriptService]
public class PostCodeService : System.Web.Services.WebService
{
private static XmlDocument _document;
private static object _lock = new object();

public static XmlDocument Document
{
get
{
lock (_lock)
{
if (_document == null)
{
_document = new XmlDocument();
_document.Load(
HttpContext.Current.Server.MapPath("~/App_Data/PostCodeService.xml"));
}
}
return _document;
}
}

public static string[] Hierarchy
{
get { return new string[] { "county", "town" }; }
}

[WebMethod]
public CascadingDropDownNameValue[] GetDropDownContents(string knownCategoryValues,
string category)
{
StringDictionary knownCategoryValuesDictionary =
CascadingDropDown.ParseKnownCategoryValuesString(knownCategoryValues);
return CascadingDropDown.QuerySimpleCascadingDropDownDocument(
Document, Hierarchy, knownCategoryValuesDictionary, category);
}
}

以上程式碼使用 Singleton Pattern 建立 XmlDocument 物件來載入 XML 文件,並加入 lock 陳述式以確保只會產生唯一個實例(Instance)。

AJAX 用戶端網頁
<table>
<tr>
<td>縣市:</td>
<td><asp:DropDownList ID="CountyDropDownList" Width="100" runat="server" /></td>
</tr>
<tr>
<td>鄉鎮區:</td>
<td><asp:DropDownList ID="TownDropDownList" Width="100" runat="server" AutoPostBack="true"
OnSelectedIndexChanged="TownDropDownList_SelectedIndexChanged" /></td>
</tr>
<tr>
<td>郵遞區號:</td>
<td>
<asp:UpdatePanel ID="PostCodeUpdatePanel" runat="server" UpdateMode="Conditional"
RenderMode="inline">
<ContentTemplate>
<asp:TextBox ID="PostCodeTextBox" Width="100" runat="server"></asp:TextBox>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="TownDropDownList"
EventName="SelectedIndexChanged" />
</Triggers>
</asp:UpdatePanel>
</td>
</tr>
</table>
<ajaxToolkit:CascadingDropDown ID="CountyCascadingDropDown" runat="server" TargetControlID="CountyDropDownList"
Category="county" PromptText="請選擇縣市" LoadingText="載入中..."
ServicePath="PostCodeService.asmx" ServiceMethod="GetDropDownContents" />
<ajaxToolkit:CascadingDropDown ID="TownCascadingDropDown" runat="server" TargetControlID="TownDropDownList"
Category="town" PromptText="請選擇鄉鎮區" LoadingText="載入中..."
ServicePath="PostCodeService.asmx" ServiceMethod="GetDropDownContents" ParentControlID="CountyDropDownList" />


 Download source code - 430 KB for ASP.NET 3.5


Share/Save/Bookmark

2 comments :: 使用 AJAX 動態載入縣市和地區

  1. 我將您的code包進了UserControl後,縣市及地區就無法正確載入清單,是什麼原因呢?
    謝謝。

  2. 請問是出現什麼樣錯誤訊息呢?

張貼留言