MVC4 - 使用 Ajax 实现级联多选列表框
MVC4 - Implement Cascading Multiselect List Boxes using Ajax
我正在使用 MVC4,我正在尝试将级联列表框实现到我的一个视图中,我一直在关注 this tutorial 并成功创建了 2 个级联下拉框,但我现在需要相同类型的列表框的功能,用户可以在其中 select 多个项目。
澄清一下,用户将能够从下拉列表中选择威胁。
在 select 威胁时,列表框将填充 select 威胁的相关安全事件,在这里用户将能够 select 多个安全事件或单个安全事件
选择 selected 安全事件后,另一个列表框将填充与 selected 安全事件关联的所有控件。
这是我目前所拥有的
查看模型
public class AddNewRiskVM
{
public SelectList RiskTypeList { get; set; }
public SelectList GroupMembersList { get; set; }
public SelectList ThreatsList { get; set; }
public SelectList SecurityEventsList { get; set; }
public List<int> SelectedSecurityEventsIDs { get; set; }
public SelectList ISOControlList { get; set; }
public List<int> AssociatedIsoIDs { get; set; }
public int ISOControlID { get; set; }
public AddNewRiskVM()
{
SelectedSecurityEventsIDs = new List<int>();
AssociatedIsoIDs = new List<int>();
}
}
控制器
public void ConfigureNewRisk(AddNewRiskVM ViewModel)
{
var RiskTypes = _DBContext.RiskTypes;
var Threats = _DBContext.Threats;
ViewModel.RiskTypeList = new SelectList(RiskTypes, "ID", "Description");
ViewModel.GroupMembersList = new SelectList(new List<GroupMember>(), "ID", "Name");
ViewModel.ThreatsList = new SelectList(Threats, "ID", "Description");
ViewModel.SecurityEventsList = new SelectList(new List<SecurityEvent>(), "ID", "Description");
ViewModel.ISOControlList = new SelectList(new List<ISOControl>(), "ID", "Description");
}
public ActionResult AddNewRisk()
{
AddNewRiskVM ViewModel = new AddNewRiskVM();
ConfigureNewRisk(ViewModel);
return View(ViewModel);
}
public IEnumerable<ISOControl> GetISOControls(int SecurityEventID)
{
var QueryResults = _DBContext
.SecurityEventHasISOControls
.Include("SecurityEventHasISOControls.ISOControlID")
.Where(x => x.SecurityEventID == SecurityEventID)
.Select(x => x.ISOControl);
return QueryResults;
}
public JsonResult GetJsonISOControl(int ID)
{
var ISOControlListT = this.GetISOControls(Convert.ToInt32(ID));
var ISOControlList = ISOControlListT.Select(x => new SelectListItem()
{
Text = x.Description,
Value = x.ID.ToString(),
});
return Json(ISOControlList, JsonRequestBehavior.AllowGet);
}
注意 - 我有与 GetISOControl 和 GetJsonControl 类似的方法,用于 The SecurityEvent
查看
<div class="containeSelect">
@using (Html.BeginForm(null, null, new { @id = string.Empty }, FormMethod.Post, new { @id = "AddNewWithSelect" }))
{
<h3>Add New Risk</h3>
<fieldset>
@Html.DropDownList("RiskType", Model.RiskTypeList, "Select Risk Type", htmlAttributes: new { @class = "CascadeInputBox", onchange = "GetMembers()"})
@Html.DropDownList("GroupMember", Model.GroupMembersList, "Select Group Member", htmlAttributes: new {@class = "CascadeInputBox", @id = "CascadeDropDownList2"})
@Html.DropDownList("Threats", Model.ThreatsList, "Select Threat", htmlAttributes: new { @class = "CascadeInputBox", onchange = "GetSecurityEvents()"})
@Html.ListBoxFor(m => m.SelectedSecurityEventsIDs, Model.SecurityEventsList, htmlAttributes: new { @id = "SelectListEvent", onchange = "GetISOControls()"})
@Html.ListBox("ISOControls", Model.ISOControlList, htmlAttributes: new { @id = "SelectListISO"})
</fieldset>
}
<script>
function GetISOControls() {
$.ajax({
url: "@Url.Action("GetJsonISOControl", "RiskAssesment")",
dataType: "json",
type: "GET",
data: { id: $("#Events").val() },
error: function () {
},
beforeSend: function () {
},
success: function (data) {
var items = "";
$.each(data, function (i, item) {
items += "<option value=\"" + item.Value + "\">" + item.Text + "</option>";
});
$("#SelectListISO").html(items);
}
});
}
</script>
<script>
function GetSecurityEvents() {
$.ajax({
url: "@Url.Action("GetJsonSecurityEvent", "RiskAssesment")",
dataType: "json",
type: "GET",
data: { id: $("#Threats").val() },
error: function () {
},
beforeSend: function () {
},
success: function (data) {
var items = "";
$.each(data, function (i, item) {
items += "<option value=\"" + item.Value + "\">" + item.Text + "</option>";
});
$("#SelectListEvent").html(items);
}
});
}
</script>
这是我第一次使用 ajax,我知道我必须以某种方式更改下面的行,因为在我的辅助方法中我没有使用字符串名称,而是使用了linq 表达式,也许这就是它工作所需的全部内容,现在我看不到其他任何东西,但也许我遗漏了什么?
data: { id: $("#Events").val() },
如果有人可以提供任何建议,尤其是 ajax,我们将不胜感激。
提前致谢
您没有 id="Events"
的元素。您所指的列表框有 id="SelectedSecurityEventIDs"
。因为它是一个 <select multiple>
它的值是一个数组所以你需要 jQuery.param method to serialie your data. Rather than polluting your markup with behavior, I recommend using Unobtrusive Javascript 所以 GetISOControls
脚本将被替换为
var isoList = $("#SelectListISO"); // cache it
$('#SelectedSecurityEventIDs').change(function() {
// create a serialized representation of the selected values
var data = $.param({ id: $(this).val() }, true);
$.ajax({
url: "@Url.Action("GetJsonISOControl", "RiskAssesment")",
dataType: "json",
type: "GET",
data: data,
success: function (data) {
isoList.empty();
$.each(data, function (i, item) {
isoList.append($('<option></option>').val(item.Value).text(item.Text));
});
}
});
});
并且控制器方法需要是
public JsonResult GetJsonISOControl(IEnumerable<int> ID)
因为您要发布一组值(您需要调整查询以适应)。另请注意,无需创建 SelectList
(它只是将未使用的额外数据发送回客户端)。应该只是
var ISOControlList = ISOControlListT.Select(x => new
{
Text = x.Description,
Value = x.ID.ToString(),
});
旁注:
@Html.ListBox("ISOControls", Model.ISOControlList, ..)
正在创建一个与您的模型无关的控件(它没有名为 ISOControls
的 属性,因此不会绑定到您的模型。我认为它应该是
@Html.ListBoxFor(m => m.AssociatedIsoIDs, Model.ISOControlList, ..)
我正在使用 MVC4,我正在尝试将级联列表框实现到我的一个视图中,我一直在关注 this tutorial 并成功创建了 2 个级联下拉框,但我现在需要相同类型的列表框的功能,用户可以在其中 select 多个项目。
澄清一下,用户将能够从下拉列表中选择威胁。
在 select 威胁时,列表框将填充 select 威胁的相关安全事件,在这里用户将能够 select 多个安全事件或单个安全事件
选择 selected 安全事件后,另一个列表框将填充与 selected 安全事件关联的所有控件。
这是我目前所拥有的
查看模型
public class AddNewRiskVM
{
public SelectList RiskTypeList { get; set; }
public SelectList GroupMembersList { get; set; }
public SelectList ThreatsList { get; set; }
public SelectList SecurityEventsList { get; set; }
public List<int> SelectedSecurityEventsIDs { get; set; }
public SelectList ISOControlList { get; set; }
public List<int> AssociatedIsoIDs { get; set; }
public int ISOControlID { get; set; }
public AddNewRiskVM()
{
SelectedSecurityEventsIDs = new List<int>();
AssociatedIsoIDs = new List<int>();
}
}
控制器
public void ConfigureNewRisk(AddNewRiskVM ViewModel)
{
var RiskTypes = _DBContext.RiskTypes;
var Threats = _DBContext.Threats;
ViewModel.RiskTypeList = new SelectList(RiskTypes, "ID", "Description");
ViewModel.GroupMembersList = new SelectList(new List<GroupMember>(), "ID", "Name");
ViewModel.ThreatsList = new SelectList(Threats, "ID", "Description");
ViewModel.SecurityEventsList = new SelectList(new List<SecurityEvent>(), "ID", "Description");
ViewModel.ISOControlList = new SelectList(new List<ISOControl>(), "ID", "Description");
}
public ActionResult AddNewRisk()
{
AddNewRiskVM ViewModel = new AddNewRiskVM();
ConfigureNewRisk(ViewModel);
return View(ViewModel);
}
public IEnumerable<ISOControl> GetISOControls(int SecurityEventID)
{
var QueryResults = _DBContext
.SecurityEventHasISOControls
.Include("SecurityEventHasISOControls.ISOControlID")
.Where(x => x.SecurityEventID == SecurityEventID)
.Select(x => x.ISOControl);
return QueryResults;
}
public JsonResult GetJsonISOControl(int ID)
{
var ISOControlListT = this.GetISOControls(Convert.ToInt32(ID));
var ISOControlList = ISOControlListT.Select(x => new SelectListItem()
{
Text = x.Description,
Value = x.ID.ToString(),
});
return Json(ISOControlList, JsonRequestBehavior.AllowGet);
}
注意 - 我有与 GetISOControl 和 GetJsonControl 类似的方法,用于 The SecurityEvent
查看
<div class="containeSelect">
@using (Html.BeginForm(null, null, new { @id = string.Empty }, FormMethod.Post, new { @id = "AddNewWithSelect" }))
{
<h3>Add New Risk</h3>
<fieldset>
@Html.DropDownList("RiskType", Model.RiskTypeList, "Select Risk Type", htmlAttributes: new { @class = "CascadeInputBox", onchange = "GetMembers()"})
@Html.DropDownList("GroupMember", Model.GroupMembersList, "Select Group Member", htmlAttributes: new {@class = "CascadeInputBox", @id = "CascadeDropDownList2"})
@Html.DropDownList("Threats", Model.ThreatsList, "Select Threat", htmlAttributes: new { @class = "CascadeInputBox", onchange = "GetSecurityEvents()"})
@Html.ListBoxFor(m => m.SelectedSecurityEventsIDs, Model.SecurityEventsList, htmlAttributes: new { @id = "SelectListEvent", onchange = "GetISOControls()"})
@Html.ListBox("ISOControls", Model.ISOControlList, htmlAttributes: new { @id = "SelectListISO"})
</fieldset>
}
<script>
function GetISOControls() {
$.ajax({
url: "@Url.Action("GetJsonISOControl", "RiskAssesment")",
dataType: "json",
type: "GET",
data: { id: $("#Events").val() },
error: function () {
},
beforeSend: function () {
},
success: function (data) {
var items = "";
$.each(data, function (i, item) {
items += "<option value=\"" + item.Value + "\">" + item.Text + "</option>";
});
$("#SelectListISO").html(items);
}
});
}
</script>
<script>
function GetSecurityEvents() {
$.ajax({
url: "@Url.Action("GetJsonSecurityEvent", "RiskAssesment")",
dataType: "json",
type: "GET",
data: { id: $("#Threats").val() },
error: function () {
},
beforeSend: function () {
},
success: function (data) {
var items = "";
$.each(data, function (i, item) {
items += "<option value=\"" + item.Value + "\">" + item.Text + "</option>";
});
$("#SelectListEvent").html(items);
}
});
}
</script>
这是我第一次使用 ajax,我知道我必须以某种方式更改下面的行,因为在我的辅助方法中我没有使用字符串名称,而是使用了linq 表达式,也许这就是它工作所需的全部内容,现在我看不到其他任何东西,但也许我遗漏了什么?
data: { id: $("#Events").val() },
如果有人可以提供任何建议,尤其是 ajax,我们将不胜感激。
提前致谢
您没有 id="Events"
的元素。您所指的列表框有 id="SelectedSecurityEventIDs"
。因为它是一个 <select multiple>
它的值是一个数组所以你需要 jQuery.param method to serialie your data. Rather than polluting your markup with behavior, I recommend using Unobtrusive Javascript 所以 GetISOControls
脚本将被替换为
var isoList = $("#SelectListISO"); // cache it
$('#SelectedSecurityEventIDs').change(function() {
// create a serialized representation of the selected values
var data = $.param({ id: $(this).val() }, true);
$.ajax({
url: "@Url.Action("GetJsonISOControl", "RiskAssesment")",
dataType: "json",
type: "GET",
data: data,
success: function (data) {
isoList.empty();
$.each(data, function (i, item) {
isoList.append($('<option></option>').val(item.Value).text(item.Text));
});
}
});
});
并且控制器方法需要是
public JsonResult GetJsonISOControl(IEnumerable<int> ID)
因为您要发布一组值(您需要调整查询以适应)。另请注意,无需创建 SelectList
(它只是将未使用的额外数据发送回客户端)。应该只是
var ISOControlList = ISOControlListT.Select(x => new
{
Text = x.Description,
Value = x.ID.ToString(),
});
旁注:
@Html.ListBox("ISOControls", Model.ISOControlList, ..)
正在创建一个与您的模型无关的控件(它没有名为 ISOControls
的 属性,因此不会绑定到您的模型。我认为它应该是
@Html.ListBoxFor(m => m.AssociatedIsoIDs, Model.ISOControlList, ..)