代码之家  ›  专栏  ›  技术社区  ›  Jason

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

  •  6
  • Jason  · 技术社区  · 15 年前

    我正在制作一个处理车辆的应用程序。我需要两个下拉列表:

    • 制造商:所有车辆制造商
    • 模型:属于选定对象的模型 make dropdownlist的值

    如何在MVC2中完成?

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

    更新 我把我最后所做的作为答案贴出来。它是 超级简单 而且效果很好。

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

    3 回复  |  直到 14 年前
        1
  •  13
  •   Jason    15 年前

    这就是我最后做的…不需要额外的插件/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);
        }
    
        2
  •  9
  •   Manaf Abu.Rous    15 年前

    这是一个很好的方法:

    假设我们有两个下拉列表,即“国家”和“城市”,则默认情况下禁用“城市”下拉列表,并且当选择国家时,会发生以下情况:

    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。 功能 负载选择 是一个helper方法,它获取最初类型的JSON对象列表 JSonSelectObject ,将其转换为要在调用下拉列表中注入的选项列表。这是一个很酷的技巧,来自于原始代码中引用的“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);
    

    此方法可能很复杂,、、但最后,您将拥有一个干净、紧凑的代码,可以在其他任何地方使用。

    我希望这是有帮助的,,


    更新

    使用post而不是get进入Ajax调用

    您可以替换 $.getJSON 使用以下代码调用,以使用post而不是get进行Ajax调用。

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

    还请记住,通过用[httppost]更改[httpget]批注来更改您的操作方法以接受post请求,并删除 JsonRequestBehavior.AllowGet 返回action方法中的结果时。

    重要提示

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

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

    然后“我们”被发送到行动方法而不是“美国”

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

    假设您的 Vehicle 视图模型:

    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方法中直接访问它们。

    如果页面是强类型化到该ViewModel,则此操作将起作用。


    注意:对于第一个列表(makelist),您可以在ViewModel中创建一个类型为selectlist的makers list,并使用HTML帮助器自动用ViewModel中的列表填充makers下拉列表。代码将如下所示:

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

    在这种情况下,为该选择生成的名称也将是“maker”(viewModel中属性的名称)。

    我希望这就是你想要的答案。

        3
  •  2
  •   Alexey Raga    15 年前

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

    如果您想使用Ajax解析值,它还可以帮助您,并且从前面的答案中消除大量代码,因此您可以集中精力处理逻辑:)

    你可以在谷歌中找到很多例子,但最终你只需要以下脚本:

    $('#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; }    
    });