天天看點

[編]使用CascadingDropDown實作級聯式下拉框使用CascadingDropDown實作級聯式下拉框

使用CascadingDropDown實作級聯式下拉框

引言

級聯式下拉框,有時也叫關聯下拉框,也是Web頁面中一個很常見的功能。就是假設有若幹個下拉框,比如說有3個,分别顯示 省份、城市、街道,當選擇某一省份後,城市下拉框僅顯示屬于該省的城市,選擇好城市之後,街道下拉框僅顯示屬于該城市的街道。記得以前做Asp的時候,做一個類似這樣的下拉框需要花費不少的力氣,編寫不少的javascript代碼。如今到了Asp.Net時代,使用Ajax Control Toolkit中的CascadingDropDown控件,再配合普通的DropDownList控件以及Web Serive,實作這樣一個功能變得非常容易了。本文将一步步來實作它。

資料庫和資料通路

這一部分和我們本文要讨論的主題實際上沒有關系,但是我們需要“可以級聯顯示”的資料,是以需要建立一個範例資料庫,同時還需要有對它的資料通路方法。對于這部分,我僅給出簡單的步驟,依然以省份、城市、街道為例:

  1. 建立一個解決方案,添加網站,并且在App_Data中建立一個資料庫SiteDB。
  2. 在SiteDB中建立三張表,分别為Province(Id, Name),City(Id, Name, ProvinceId),Street(Id, Name, CityId)。其中Id為int自增類型,且為主鍵;Name為Varchar(50)。ProvinceId和CityId則為外鍵。
  3. 為上面三個表添加一些範例資料,如果你覺得麻煩,那麼可以拷貝本文附帶代碼中的資料庫。
  4. 在App_Code中添加一個SiteDataSet資料集。然後打開“Server Explore(伺服器浏覽器)”将上面三張表拖進去。
  5. 分别對它們的TableAdapter進行配置,其中Province的為獲得全部資料,而City和Street分别根據ProvinceId和CityId擷取資料,最終的SiteDataSet如下圖所示:
[編]使用CascadingDropDown實作級聯式下拉框使用CascadingDropDown實作級聯式下拉框

OK,這樣資料庫和資料通路就完畢了,接下來我們看下Web頁面。

Web頁面布局和設定

首先我們在站點中添加一個“Ajax-enabled WCF Service(啟用了AJAX的WCF服務)”,命名為AddressService,暫時不用管它的實作。在ScriptManager中對它進行注冊(在本文中這裡不注冊也可以):

<asp:ScriptManager ID="ScriptManager1" runat="server">

    <Services>

        <asp:ServiceReference Path="~/AddressService.svc" />

    </Services>

</asp:ScriptManager>

打開Default.aspx,像下圖這樣對頁面進行布局:

[編]使用CascadingDropDown實作級聯式下拉框使用CascadingDropDown實作級聯式下拉框

三個DropDownList分别的Id為ddlProvince、ddlCity、ddlStreet。之後從AjaxControlToolkit中拖三個CascadingDropDown到頁面上,像下面這樣對其進行配置:

<ajaxControlToolkit:CascadingDropDown ID="CascadingDropDown1"

        runat="server"

        TargetControlID="ddlProvince"

        Category="Province"

        PromptText="請選擇省份...."

        LoadingText="加載中,請稍後 ..."

        ServicePath="AddressService.svc"

        ServiceMethod="GetProvince"

        >

</ajaxControlToolkit:CascadingDropDown>

<ajaxControlToolkit:CascadingDropDown ID="CascadingDropDown2"

        runat="server"                 

        TargetControlID="ddlCity"

        ParentControlID="ddlProvince"

        Category="City"

        PromptText="請選擇城市...."

        ServiceMethod="GetCity"

</ajaxControlToolkit:CascadingDropDown>    

<ajaxControlToolkit:CascadingDropDown ID="CascadingDropDown3"

        TargetControlID="ddlStreet"

        ParentControlID="ddlCity"

        Category="Street"

        ServiceMethod="GetStreet"

這三個CascadingDropDown分别對應之前添加的通常的DropDownList控件,下面是對其各個屬性的一個簡單說明:

  • TargetControlID:與之協作的DropDownList控件的ID。
  • ParentControlID:父級下拉框的ID,顯然頂級下拉框ddlProvince不含有父級下拉框,是以不含有ParentControlID。
  • Category:此下拉框的“類别”,也可以稱為名稱,具體使用到後面再說,這裡說了也不好了解。
  • PromptText:進行選擇之前顯示的文本。
  • LoadingText:加載時顯示的文本,因為需要與服務端進行通信,是以難免會産生延遲,這裡的文本便是在延遲時顯示的文本。
  • ServicePath:擷取資料時的Web服務。此處即為我們的WCF服務。
  • ServiceMethod:擷取資料的方法。這些方法由WCF服務實作,顯然我們暫時并沒有實作它。

好了,現在頁面部分就設定完畢了,我們最後看下WCF服務的實作,它僅僅是使用第一步建立的資料集來擷取資料。

編寫WCF服務代碼

WCF服務所要實作的實際就是上面CascadingDropDown中所設定的三個用于擷取資料的方法:GetProvince()、GetCity()和GetStreet()。因為需要在頁面的後置代碼中使用AjaxControlToolkit所定義的類型,是以如果你和我一樣使用了GAC來部署AjaxControlToolkit程式集的話,那麼需要首先在Web.Config中對它進行注冊:

<compilation debug="true">

    <assemblies>

        <add assembly="AjaxControlToolkit, Version=3.0.20820.37372, Culture=neutral, PublicKeyToken=28f01b0e84b6d53e"/>

        <!-- 省略其他 -->

    </assemblies>

</compilation>

接下來我們來實作這三個方法,先看App_Code中AddressService下的GetProvince()方法的實作,顯然,它獲得所有的省份:

public class AddressService

{

    [OperationContract]

    public CascadingDropDownNameValue[] GetProvince(string knownCategoryValues, string category)

    {

        Thread.Sleep(1000); // 等待1秒,模拟網絡延遲

        SiteDataSetTableAdapters.ProvinceTableAdapter provinceAdapter

            = new SiteDataSetTableAdapters.ProvinceTableAdapter();

        SiteDataSet.ProvinceDataTable provinceTable = provinceAdapter.GetProvince();

        List<CascadingDropDownNameValue> values = new List<CascadingDropDownNameValue>();

        foreach (SiteDataSet.ProvinceRow province in provinceTable) {

            string id = province.Id.ToString();

            string name = province.Name;

            values.Add(new CascadingDropDownNameValue(name, id));

        }

        return values.ToArray();

    }

}

我們先看下方法的簽名,第2個參數category即是我們在CascadingDropDown中定義的category屬性的值,它傳到了這裡供我們做一些處理。第1個參數以“Category:Id”的形式包含父下拉框的category值和id值,因為省份為頂級下拉框,是以此時knownCategoryValues為空字元串。傳回值為一個CascadingDropDownNameValue數組,其實就是一個鍵/值對,用于傳回給用戶端進行綁定。

方法的内容我覺得不需要有任何解釋,都是最平常不過的強類型DataSet的基本操作。需要注意的是Thread.Sleep(1000),這裡是為了模拟網絡延遲的效果,以讓控件能夠顯示出LoadingText的效果。

接下來,我們再看剩下兩個方法GetCity和GetStreet方法的實作:

[OperationContract]

public CascadingDropDownNameValue[] GetCity(string knownCategoryValues, string category)

    Thread.Sleep(1000);

    StringDictionary keyValue =

        CascadingDropDown.ParseKnownCategoryValuesString(knownCategoryValues);

    int provinceId = Convert.ToInt32(keyValue["Province"]);

    SiteDataSetTableAdapters.CityTableAdapter cityAdapter =

        new SiteDataSetTableAdapters.CityTableAdapter();

    SiteDataSet.CityDataTable cityTable = cityAdapter.GetCityByProvinceId(provinceId);

    List<CascadingDropDownNameValue> values = new List<CascadingDropDownNameValue>();

    foreach (SiteDataSet.CityRow city in cityTable) {

        string id = city.Id.ToString();

        string name = city.Name;

        values.Add(new CascadingDropDownNameValue(name, id));

    return values.ToArray();

public CascadingDropDownNameValue[] GetStreet(string knownCategoryValues, string category) {

    int cityId = Convert.ToInt32(keyValue["City"]);

    SiteDataSetTableAdapters.StreetTableAdapter streetAdapter =

        new SiteDataSetTableAdapters.StreetTableAdapter();

    SiteDataSet.StreetDataTable streetTable = streetAdapter.GetStreetByCityId(cityId);

    foreach (SiteDataSet.StreetRow street in streetTable) {

        string id = street.Id.ToString();

        string name = street.Name;

這兩個方法是完全類似的,是以我們僅就GetCity()方法說明。假如我們此刻在頁面選擇了省份,為“陝西”,且它的id為“2”,那麼按照上面的說明,knownCategoryValues包含的值為“Province:2”,它含有了父控件的category值和選中的id值,通過它我們就可以獲得選中的省份id。我們并不需要手動去處理這個字元串,比如使用Split()方法,而可以使用CascadingDropDown.ParseKnownCategoryValuesString靜态方法來完成,如上面的代碼所示。

在獲得了省份id之後,我們可以調用DataAdapter上的方法,來根據省份id獲得其下所包含的城市,這些代碼大家應該已經很熟悉了。

好了,現在一切已經就緒,大家可以打開頁面看一下實際的效果了:

[編]使用CascadingDropDown實作級聯式下拉框使用CascadingDropDown實作級聯式下拉框

總結

在這篇文章中,我們又實作了Web中的一個常見功能:級聯式下拉框。我們先建立了範例資料庫,以及一個強類型DataSet用作資料通路。随後對Web頁面進行了布局,設定了控件屬性。最後編寫了WCF服務,擷取用戶端所需要的資料。

感謝閱讀,希望這篇文章能給你帶來幫助!