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));
});
});
});
我正在尝试创建一个包含两个 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));
});
});
});