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

发布于 2024-09-19 15:30:21 字数 405 浏览 4 评论 0原文

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

  • 品牌:所有车辆品牌
  • 型号:属于所选的型号 Make DropDownList 的值

这在 MVC2 中是如何完成的?

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

更新我发布了我最终所做的事情作为答案。它超级简单而且效果很好。

如果您愿意,也可以使用 get,但您必须指定您想要这样... return Json(citiesList, JsonRequestBehavior.AllowGet);

I am making an application that deals with vehicles. I need two DropDownLists:

  • Makes: All Vehicle Makes
  • Models: Models that belong to the selected
    value of the Make DropDownList

How is this done in MVC2?

My Idea: Do I use an ajax call when my first list is selected and then pull back the Models to bind to the Model DDL? How would model binding come into play that way?

UPDATE I posted what I ended up doing as an answer. It is super simple and works great.

You can use a get too if you feel so inclined, but you have to specify that you want to like so... return Json(citiesList, JsonRequestBehavior.AllowGet);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

终弃我 2024-09-26 15:30:21

这就是我最终要做的...不需要额外的插件/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');
                });
            }
        });
    });

Action

    [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);
    }

This is what I ended up doing... Didn't need additional plugins / 1000 Lines of code...

The 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>

The 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');
                });
            }
        });
    });

The Action

    [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);
    }
她如夕阳 2024-09-26 15:30:21

这是一个很好的方法:

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

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.

原始代码的来源为< a href="http://www.kingwilder.com/" rel="nofollow noreferrer">King Wilder 来自 MVC 中心。此示例是从 Golf Tracker 中的代码中提取的简化版本系列

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对象列表/code> ,将其转换为要在调用下拉列表中注入的选项列表。这是原始代码中引用的“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);

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

我希望这对您有帮助,,,


更新

在 AJAX 调用中使用 POST 而不是 GET

您可以将 $.getJSON 调用替换为以下内容使用 POST 而不是 GET 进行 ajax 调用的代码。

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

还记得通过将 [HttpGet] 注释更改为 [HttpPost] 来更改您的 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,您可以直接在操作方法中访问它们。

如果页面是该 ViewModel 的强类型,这将起作用。


注意:对于第一个列表(制作列表),您可以在 ViewModel 中创建 SelectList 类型的 MakersList 并使用 HTML 帮助程序自动填充您的制作者下拉列表以及 ViewModel 中的列表。代码将如下所示:

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

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

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

Here's a nice way to do it :

Suppose that we have two drop lists, country and city ,, the city drop down is disabled by default and when a country is selected the following happens :

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.

Credits for the original code goes to King Wilder from MVC Central. This example is a simplified version that was extracted from his code in the 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);
        });
    }
}

Action Method

[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);
}

Important Notes:

1. The JsonSelectObject help make things easier when converting the results to an option tag as it will be used in the javascript loadSelect method below.
it's basically a class with the two properties value and caption :

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

2. The function loadSelect is a helper method that takes a list of json objects originally of typeJsonSelectObject , converts it to a list of options to be injected in calling drop down list. it's a cool trick from the "jQuery In Action" book as referenced in the original code, it's included in a jquery.jqia.selects.js file that you will need to reference. Here's the code in that js file :

(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);

This method might be complex ,,, but at the end you will have a clean & compact code that you can use everywhere else.

I hope this was helpful ,,,


Update

Using POST instead of GET in the AJAX call

You can replace the $.getJSON call with the following code to make the ajax call using POST instead of GET.

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

also remember to change your Action method to accept POST requests by changing the [HttpGet] annotation with [HttpPost] and remove the JsonRequestBehavior.AllowGet when returning the result in the Action Method.

Important Note

Note that we are using the value of the selected item rather than the name. for example if the user selected the following option.

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

then "US" is sent to the Action method and not "United States"

Update 2: Accessing the Selected Values In The Controller

suppose that you have the following two properties in your Vehicle viewmodel:

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

and you name your select elements with the same name as your ViewModel properties.

<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>

Then the selected values will be automatically Bound to your ViewModel and you can access them directly in you Action Method.

This will work if the page is Strongly Typed to that ViewModel.


Note: For the first list ( The Makes List ) you can create a MakersList of type SelectList in your ViewModel and use the HTML helper to automatically populate your Makers Drop Down with the list in your ViewModel. the code will look something like this :

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

In that case the generated name for this select will be also "Maker" (the name of the property in the ViewModel).

I hope this is the answer you are looking for.

琉璃梦幻 2024-09-26 15:30:21

最简单的方法是使用 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; }    
});

The simpliest way is to use jQuery "cascade" plugin.
http://plugins.jquery.com/project/cascade (look at the demo page there).

If you want to resolve value using ajax, it also helps you and it eliminates a lot of code from the previous answer, so you can concentrate on your logic :)

You can find a lot of examples in google, but you end up with just the following script:

$('#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; }    
});
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文