使用基于另一个下拉列表的MVC2填充下拉列表(级联DropDownList)

时间:2010-09-18 22:41:11

标签: c# asp.net asp.net-mvc-2 drop-down-menu

我正在制作处理车辆的应用程序。我需要两个DropDownLists:

  • 制作:所有车辆制作
  • 模型:属于所选模型 Make DropDownList的值

如何在MVC2中完成?

我的想法:当我选择第一个列表时,是否使用ajax调用,然后撤回模型以绑定到模型DDL?模型绑定将如何发挥作用?

更新我发布了我最终做的答案。这是超级简单并且效果很好。

如果您有这种倾向,也可以使用get,但是您必须指定您想这样... return Json(citiesList, JsonRequestBehavior.AllowGet);

3 个答案:

答案 0 :(得分:13)

这就是我最终做的......不需要额外的插件/ 1000行代码......

Html

//The first DDL is being fed from a List in my ViewModel, You can change this...
<%: Html.DropDownList("MakeList", new SelectList(Model.Makes, "ID", "Name")) %>
<select id="ModelID" name="ModelID" disabled="disabled"></select>

JQuery

    $(document).ready(function () {
        $('#MakeList').change(function () {
            $.ajaxSetup({ cache: false });
            var selectedItem = $(this).val();
            if (selectedItem == "" || selectedItem == 0) {
                //Do nothing or hide...?
            } else {
                $.post('<%: ResolveUrl("~/Sell/GetModelsByMake/")%>' + $("#MakeList > option:selected").attr("value"), function (data) {
                    var items = "";
                    $.each(data, function (i, data) {
                        items += "<option value='" + data.ID + "'>" + data.Name + "</option>";
                    });
                    $("#ModelID").html(items);
                    $("#ModelID").removeAttr('disabled');
                });
            }
        });
    });

行动

    [HttpPost]
    public ActionResult GetModelsByMake(int id)
    {
        Models.TheDataContext db = new Models.TheDataContext();
        List<Models.Model> models = db.Models.Where(p=>p.MakeID == id).ToList();

        return Json(models);
    }

答案 1 :(得分:9)

这是一个很好的方法:

假设我们有两个下拉列表,国家和城市,默认情况下禁用城市下拉列表,当选择国家/地区时,会发生以下情况:

1. city drop down list gets enabled.
2. An AJAX call is made to an action method with the selected country and a list of cities is returned.
3. the city drop down list is populated with the JSON data sent back.

原始代码的积分从King Wilder转到MVC Central。此示例是从Golf Tracker Series中的代码中提取的简化版本。

<强> HTML

<select id="Country">
// a List of Countries Options Goes Here.
</select></div>

<select id="City" name="City" disabled="disabled">
// To be populated by an ajax call
</select>

<强>的JavaScript

// Change event handler to the first drop down ( Country List )
$("#Country").change(function() {
    var countryVal = $(this).val();
    var citySet = $("#City");

    // Country need to be selected for City to be enabled and populated.
    if (countryVal.length > 0) {
        citySet.attr("disabled", false);
        adjustCityDropDown();
    } else {
        citySet.attr("disabled", true);
        citySet.emptySelect();
    }
});

// Method used to populate the second drop down ( City List )   
function adjustCityDropDown() {
    var countryVal = $("#Country").val();
    var citySet = $("#City");
    if (countryVal.length > 0) {
        // 1. Retrieve Cities that are in country ...
        // 2. OnSelect - enable city drop down list and retrieve data
        $.getJSON("/City/GetCities/" + countryVal ,
        function(data) {
            // loadSelect - see Note 2 bellow
            citySet.loadSelect(data);
        });
    }
}

行动方法

[HttpGet]
public ActionResult GetCities(string country)
{
    Check.Require(!string.IsNullOrEmpty(country), "State is missing");

    var query  = // get the cities for the selected country.

    // Convert the results to a list of JsonSelectObjects to 
    // be used easily later in the loadSelect Javascript method.         
    List<JsonSelectObject> citiesList = new List<JsonSelectObject>();
        foreach (var item in query)
        {
            citiesList.Add(new JsonSelectObject { value = item.ID.ToString(),
                                                  caption = item.CityName });
        }        

    return Json(citiesList, JsonRequestBehavior.AllowGet);
}

重要提示:

1。在将结果转换为选项标记时,JsonSelectObject有助于简化操作,因为它将在下面的javascript loadSelect方法中使用。 它基本上是一个具有两个属性值和标题的类:

public class JsonSelectObject
{
    public string value { get; set; }
    public string caption { get; set; }
}

2. 函数loadSelect是一个辅助方法,它获取最初类型为JsonSelectObject的json对象列表,将其转换为要注入的选项列表调用下拉列表。它是原始代码中引用的“jQuery In Action”一书中的一个很酷的技巧,它包含在您需要引用的jquery.jqia.selects.js文件中。这是js文件中的代码:

(function($) {
    $.fn.emptySelect = function() {
        return this.each(function() {
            if (this.tagName == 'SELECT') this.options.length = 0;
        });
    }

    $.fn.loadSelect = function(optionsDataArray) {
        return this.emptySelect().each(function() {
            if (this.tagName == 'SELECT') {
                var selectElement = this;
                selectElement.add(new Option("[Select]", ""), null);
                $.each(optionsDataArray, function(index, optionData) {
                    var option = new Option(optionData.caption,
                                  optionData.value);
                    if ($.browser.msie) {
                        selectElement.add(option);
                    }
                    else {
                        selectElement.add(option, null);
                    }
                });
            }
        });
    }

})(jQuery);

这种方法可能很复杂,但最后你会有一个干净的&amp;紧凑的代码,你可以在其他地方使用。

我希望这很有用,,,


<强>更新

在AJAX通话中使用POST代替GET

您可以使用以下代码替换$.getJSON调用,以使用POST而不是GET进行ajax调用。

$.post("/City/GetCities/", { country: countryVal }, function(data) {
     citySet.loadSelect(data);
 });

还记得通过使用[HttpPost]更改[HttpGet]注释来更改Action方法以接受POST请求,并在Action方法中返回结果时删除JsonRequestBehavior.AllowGet

重要提示

请注意,我们使用的是所选项目的值而不是名称。例如,如果用户选择了以下选项。

<option value="US">United States</option>

然后“US”被发送到Action方法而不是“United States”

更新2:访问控制器中的选定值

假设您在Vehicle viewmodel中有以下两个属性:

public string Maker { get; set; }
public string Model { get; set; }

并使用与ViewModel属性相同的名称命名选择元素。

<select id="Maker" name="Maker">
// a List of Countries Options Goes Here.
</select></div>

<select id="Model" name="Model" disabled="disabled">
// To be populated by an ajax call
</select>

然后,所选值将自动绑定到您的ViewModel,您可以直接在Action Method中访问它们。

如果页面强烈输入到该ViewModel,这将有效。


注意:对于第一个列表(The Makes List),您可以在ViewModel中创建一个类型为SelectList的MakersList,并使用HTML帮助器自动使用ViewModel中的列表填充Makers Drop Down。代码看起来像这样:

<%= Html.DropDownListFor(model => model.Maker, Model.MakersList) %>

在这种情况下,此选择的生成名称也将是“Maker”(ViewModel中属性的名称)。

我希望这是您正在寻找的答案。

答案 2 :(得分:2)

最简单的方法是使用jQuery“cascade”插件。 http://plugins.jquery.com/project/cascade(查看那里的演示页面)。

如果你想使用ajax解析价值,它也可以帮助你,并且它从前面的答案中消除了很多代码,所以你可以专注于你的逻辑:)

您可以在google中找到很多示例,但最终只能使用以下脚本:

$('#myChildSelect').cascade('#myParentSelect', 
{
    ajax: '/my/url/action',
    template: function(item) {
        return "<option value='" + item.value + "'>" + item.text + "</option>"; },
    match: function(selectedValue) { return this.when == selectedValue; }    
});