ASP.Net MVC Cascaded DropDownList – 在ASP.Net MVC 中實現級聯下拉框

在網頁上..很多時候都會出現一些Cascaded DropDownList...
主要是因為有一些資料..是要依賴之前選擇的資料..再從資料庫找出相關的資料..給客戶選擇的
例如:
國家 和城市
年/月/日等等…
E.G.
2 pairs of DropDownList represent Food Category and Food
ASP.Net 上 可以很簡單地用 DropDownList Auto-Postback 的特性..
今到使用者選擇了DropDownList的內容後做一個PostBack..
使Server從新再DataBind 和他想關的DropDownList
很簡單便可以實現這個效果了
dropdownlist without linking together

ASP.Net MVC…由於沒有PostBack這個特性的關係.. 我們便要做多一點功夫了
解決方法:
我們會用 Food CategoryFood 的關係做這個示範的
會用到4個DropDownList
Food Category ID, Food Category Name, Food ID, Food Name
2對的DropDownList.

每一個Food 都有一個Food Category ID
所以每當用戶更改 Food Category一對DropDownList之後
下面的Food DropDownList便會跟著更新

我們會需要在View 上使用到JQuery 來做一個Ajax Request 取得 和Food Category 相關的Food 的資料的
和在Controller上建立一個return JSON 的 Action
Model
C#

//這是我為這個DropDownList 所建立的一個Model..
//他有一個Food Category List和Food List 用來示範有Cascading Drop Down List的情況的
 public class FoodCategory_SelectionOptions_Model
    {
        public List FoodCategory_List { get; set; }
        public List Food_List { get; set; }
    }

Controller
C#

// 大至上和之前的POST 差不多..所以我也不多加註釋了
  private ShareChiWai_Model Share_Model;

        public CascadingDropDownListController()
        {
            Share_Model = new ShareChiWai_Model();
        }

        public ActionResult Index()
        {
            FoodCategory_SelectionOptions_Model MainModel = new FoodCategory_SelectionOptions_Model();
            List Category_List = Share_Model.Get_Food_Categories_List();
            MainModel.FoodCategory_List = Category_List;

            if (Category_List.Count > 0)
            {
                MainModel.Food_List = Share_Model.Get_FoodByCategoryID_List(Category_List[0].FoodCategory_ID);
            }

            return View(MainModel);
        }
//這個功能用來把ShareChiWai_Model的Get_FoodByCategoryID_List的結果轉成JSON Result給我們的.cshtml 去把資料重新再Assign 到dropdownlist上
        public JsonResult SelectedFoodCategory(string Food_Category_ID)
        {
            List Food_List = Share_Model.Get_FoodByCategoryID_List(Food_Category_ID);
//我們會用到 Json(Model,和 Request的方法)
            return Json(Food_List, JsonRequestBehavior.AllowGet);

        }

.cshtml

//大至上和之前的POST 差不多.. 大家有什麼不明白或有更好的方法歡迎大家留言
@model ShareChiWaiWebTutorial.Models.FoodCategory_SelectionOptions_Model
@{
    var ddl_FoodCategories = new SelectList(Model.FoodCategory_List, "FoodCategory_ID", "FoodCategory_ID");
    string SelectedFoodCategory = Model.FoodCategory_List[0].FoodCategory_ID;
    var ddl_FoodCategoriesName = new SelectList(Model.FoodCategory_List.OrderBy(f=>f.FoodCategory_Name), "FoodCategory_ID", "FoodCategory_Name", SelectedFoodCategory);

    var ddl_Food = new SelectList(Model.Food_List, "Food_ID", "Food_ID");
    string SelectedFood = Model.Food_List[0].Food_ID;
    var ddl_FoodName = new SelectList(Model.Food_List.OrderBy(f=>f.Food_Name), "Food_ID", "Food_Name", SelectedFood);
 }

 Category:
@Html.DropDownList("ddl_FoodCategories", ddl_FoodCategories)
@Html.DropDownList("ddl_FoodCategoriesName", ddl_FoodCategoriesName)
<br />
Food:
@Html.DropDownList("ddl_Food", ddl_Food)
@Html.DropDownList("ddl_FoodName", ddl_FoodName)

Javascript – on the .cshtml 頁

<script type="text/javascript">

    $(document).ready(function () {
//在這裡我們做一些 和 SelectedIndexChanged 的 功能 
        //Set up Selected Index Change Like Event For ddl_FoodCategories and #ddl_FoodCategoriesName
        DDL_SelectedIndexChanged('#ddl_FoodCategories', '#ddl_FoodCategoriesName');
        DDL_SelectedIndexChanged('#ddl_FoodCategoriesName', '#ddl_FoodCategories');
        //Set up Selected Index Change Like Event For ddl_Food and #ddl_FoodName
        DDL_SelectedIndexChanged('#ddl_Food', '#ddl_FoodName');
        DDL_SelectedIndexChanged('#ddl_FoodName', '#ddl_Food');
    });

    function DDL_SelectedIndexChanged(DDL1, DDL2) {
//當感到有 .Change event的時候 進行以下的function
        $(DDL1).change(function () {
//把DDL1 的value assign到DDL2上
            $(DDL2).val(this.value);
//如果DDL1是 ddl_FoodCategories或ddl_FoodCategoriesName 時我們要進行一個Jquery 的AJAX Call 
//因為 我們暫時不用為用戶改變ddl_Food或ddl_FoodName 時進行任何特別的動作的.. 所以 便用了 "#ddl_FoodCategories" || DDL1 == "#ddl_FoodCategoriesName"
            if (DDL1 == "#ddl_FoodCategories" || DDL1 == "#ddl_FoodCategoriesName") {
//我們用了RAZOR 的syntax 來建立我們的連結
//用了Jquery的 getJSON方法 向CascadingDropDownList Controller 的 SelectedFoodCategory 取資料
//我們的Parameter是 Food_Category_ID 用來取出和這個Food Category 有關的Food 的資料
                $.getJSON('@Url.Action("SelectedFoodCategory", "CascadingDropDownList")', { Food_Category_ID: this.value }, function (FoodInfo) {
//取得資料後 我們便可以把資料assign 到我們現有的 ddl_Food 和ddl_FoodName上了
                    var ddl_Food = $("#ddl_Food");
                    var ddl_FoodName = $("#ddl_FoodName");
//首先我們要清楚將會被更新的Dropdownlist 的內容 -- 可以使用object.empty() 來實現的
                    ddl_Food.empty();
                    ddl_FoodName.empty();
之後用jquery 的 $.each 來loop though我們的 JSON array
                    $.each(FoodInfo, function (index, FoodInfo) {
//在這裡把Json Array的相關內容加進我們的Dropdownlist上 //這個是給ddl_Food的
                        ddl_Food.append(
                        $('<option/>')
                            .attr('value', FoodInfo.Food_ID)
                            .text(FoodInfo.Food_ID));
/這個是給ddl_FoodName的
                        ddl_FoodName.append(
                        $('<option/>')
                            .attr('value', FoodInfo.Food_ID)
                            .text(FoodInfo.Food_Name))
                    });
                });

            }
        });
    }</script>

完成品
Cascading Drop Down List completed

大家會發現… 雖然可以做到 Cascaded DropDownList/級聯下拉框 的效果.. 但是還有一些美中不足的地方..
例如.. Label/DropDownList 大小不一樣
第二層的下拉框排序有點亂..

Cascading Drop Down List Sorting Issue
Hope you find it useful

2 thoughts on “ASP.Net MVC Cascaded DropDownList – 在ASP.Net MVC 中實現級聯下拉框

    1. ShareChiWai Post author

      不好意思.. 暫時不能Email你 這個Sample Code..因為這個Sample 是在我HDD 壞之前做的..
      所以要待我再次建立一個demo 才可以email 你…最近比較忙..
      我會盡快完成的

      Reply

Leave a Reply