MVC 4 Razor - 创建动态下拉列表

Posted

技术标签:

【中文标题】MVC 4 Razor - 创建动态下拉列表【英文标题】:MVC 4 Razor - Creating a dynamic DropDownList 【发布时间】:2015-03-22 21:59:47 【问题描述】:

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

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

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

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

谢谢!

【问题讨论】:

【参考方案1】:

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

选择国家/地区时用于获取状态的 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 的实用方法

【讨论】:

这正是我想要的!谢谢。【参考方案2】:

您的第一个选择的.change 事件应通过调用基于所选值返回选项数据的服务器方法填充第二个选择。给定以下视图模型

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

【讨论】:

也是一个很好的答案。谢谢!

以上是关于MVC 4 Razor - 创建动态下拉列表的主要内容,如果未能解决你的问题,请参考以下文章

根据下拉列表的值创建 2 个下拉列表和一个表

根据上一个列表中选择的值填充下拉列表(asp.net mvc3)

使用 Select2 jquery 进行多选的 ASP MVC 下拉列表

如何从现有 SQL DB ASP.Net MVC 4 在下拉列表中填充数据

在 mvc JavaScript 中的下拉更改选择上加载列

如何使用 ASP.NET Core Razor 页面预选下拉列表中的项目