MVC 4 Razor - 创建动态 DropDownList

MVC 4 Razor - Creating a dynamic DropDownList

我正在尝试创建一个包含两个 DropDownList 的视图。第二个 DropDownList 中可用的选项取决于用户在第一个中选择的内容。我将此数据传递到我在 ViewBag 中的视图,如下所示:

   List<SelectListItem> firstBoxChoices =  ViewBag.firstBoxChoices;
   Dictionary<string, List<SelectListItem>> secondBoxDict = ViewBag.secondBoxDict;

第一个对象具有第一个 DropDownList 的选项。当用户选择其中之一时,我需要从我的词典中为第二个 DropDownList 获取适当的选项列表。我只是不知道如何实现这一目标。如果我在 Javascript onchange() 函数中获得第一个 DropDownList 的新选择,似乎没有任何方法可以将此值用作我的 C# 字典的键。

当然,我在网上看到过这个功能,所以我知道它一定是可行的。我怎样才能做到这一点?

谢谢!

有几种方法可以做到这一点,而不必强迫您在模型中存储所有可能的数据项,我更喜欢使用 Javascript/JQuery。这是 Country/State 级联下拉列表的示例:

Javascript 用于在选择国家时获取状态:

<script type="text/javascript">
    function AppendUrlParamTokens(url, params) {

        for (var param in params) {
            if (params[param] == null) {
                delete params[param];
            }
        }

        return url + "?" + jQuery.param(params);
    }

    function OnCountriesChange(ddl) {
        jQuery.getJSON(AppendUrlParamTokens('@Url.Action("GetStates", "Data")', { countryId: ddl.options[ddl.selectedIndex].value }), function (result) {
            var target = jQuery('#states_ddl');
            target.empty();
            jQuery(result).each(function() {
                jQuery(document.createElement('option'))
                    .attr('value', this.Value)
                    .text(this.Text)
                    .appendTo(target);
            });
        });
    };
</script>

国家/地区下拉列表:

@Html.DropDownListFor(model => model.Country, new SelectList(Model.Countries, "Value", "Text", Model.PreviousCountrySelected), "(Select One)", new { id = "countries_ddl", onchange = "OnCountriesChange(this)" })

状态下拉列表:

Html.DropDownListFor(model => model.State,
                              Model.States != null
                                       ? new SelectList(Model.States, "Value", "Text", Model.PreviousStateSelected)
                                       : new SelectList(new List<SelectListItem>(), "Value", "Text"),
                              new { id = "states_ddl" })

检索状态的控制器方法:

public ActionResult GetStates(short? countryId)
{
    if (!countryId.HasValue)
    {
        return Json(new List<object>(), JsonRequestBehavior.AllowGet);
    }

    var data = GetAllStatesForCountry(countryId.Value).Select(o => new { Text = o.StateName, Value = o.StateId });

    return Json(data, JsonRequestBehavior.AllowGet);
}

想法是,在选择下拉列表 1 时,您使用 ajax 来检索第二个下拉列表的值。

编辑:忘记包含构建 url 的实用方法

您的第一个 select 的 .change 事件应该通过调用一个服务器方法来填充第二个 select,returns 选项数据基于 selected值。给定以下视图模型

public class MyModel
{
  [Required(ErrorMessage = "Please select an organisation")]
  [Display(Name = "Organisation")]
  public int? SelectedOrganisation { get; set; }
  [Required(ErrorMessage = "Please select an employee")]
  [Display(Name = "Employee")]
  public int? SelectedEmployee { get; set; }
  public SelectList OrganisationList { get; set; }
  public SelectList EmployeeList { get; set; }
}

控制器

public ActionResult Edit(int ID)
{
  MyModel model = new MyModel();
  model.SelectedOrganisation = someValue; // set if appropriate
  model.SelectedEmployee = someValue; // set if appropriate
  ConfigureEditModel(model); // populate select lists
  return View(model);
}

[HttpPost]
public ActionResult Edit(MyModel model)
{
  if(!ModelState.IsValid)
  {
    ConfigureEditModel(model); // reassign select lists
    return View(model);
  }
  // save and redirect
}

private void ConfigureEditModel(MyModel model)
{
  // populate select lists
  model.OrganisationList = new SelectList(db.Organisations, "ID", "Name");
  if(model.SelectedOrganisation.HasValue)
  {
    var employees = db.Employees.Where(e => e.Organisation == model.SelectedOrganisation.Value);
    model.EmployeeList = new SelectList(employees, "ID", 
  }
  else
  {
    model.EmployeeList = new SelectList(Enumerable.Empty<SelectListItem>());
  }
}

[HttpGet]
public JsonResult FetchEmployees(int ID)
{
  var employees = db.Employees.Where(e => e.Organisation == ID).Select(e => new
  {
    ID = e.ID,
    Name = e.Name
  });
  return Json(employees, JsonRequestBehavior.AllowGet);
}

查看

@model MyModel
....
  @Html.LabelFor(m => m.SelectedOrganisation)
  @Html.DropDownListFor(m => m.SelectedOrganisation, Model.OrganisationList, "-Please select-")
  @Html.ValidationMessageFor(m => m.SelectedOrganisation)
  @Html.LabelFor(m => m.SelectedEmployee)
  @Html.DropDownListFor(m => m.SelectedEmployee, Model.EmployeeList, "-Please select-")
  @Html.ValidationMessageFor(m => m.SelectedEmployee)
....

脚本

var url = '@Url.Action("FetchEmployees")';
var employees = $('SelectedEmployee');
$('#SelectedOrganisation').change(function() {
  employees.empty();
  if(!$(this).val()) {
    return;
  }
  employees.append($('<option></option>').val('').text('-Please select-'));
  $.getJson(url, { ID: $(this).val() }, function(data) {
    $.each(data, function(index, item) {
      employees.append($('<option></option>').val(item.ID).text(item.Text));
    });
  });
});