最近在我的第一个ASP.Net MVC2网络应用程序上工作时,当我需要在列表框中选择多个值时,我遇到了一些问题。我用一些jQuery解决了这个问题,但是继续编写了一些非常简单的代码来演示。我正在使用EF作为模型,有两个实体 - Customers和HelpDeskCalls:
控制器:
public ActionResult Edit(int id)
{
Customer currCustomer = ctx.Customers.Include("HelpDeskCalls").Where(c => c.ID == id).FirstOrDefault();
List<HelpDeskCall> currCustCalls = (ctx.HelpDeskCalls.Where(h => h.CustomerID == id)).ToList();
List<SelectListItem> currSelectItems = new List<SelectListItem>();
List<String> selectedValues = new List<string>();
foreach (HelpDeskCall currCall in currCustCalls)
{
bool isSelected = (currCall.ID % 2 == 0) ? true : false;
//Just select the IDs which are even numbers...
currSelectItems.Add(new SelectListItem() { Selected = isSelected, Text = currCall.CallTitle, Value = currCall.ID.ToString() });
//add the selected values into a separate list as well...
if (isSelected)
{
selectedValues.Add(currCall.ID.ToString());
}
}
ViewData["currCalls"] = (IEnumerable<SelectListItem>) currSelectItems;
ViewData["currSelected"] = (IEnumerable<String>) selectedValues;
return View("Edit", currCustomer);
}
查看:
<div class="editor-field">
<%: Html.ListBoxFor(model => model.HelpDeskCalls, new MultiSelectList(Model.HelpDeskCalls, "ID", "CallTitle", (IEnumerable) ViewData["currSelected"]), new { size = "12" })%>
<%: Html.ListBoxFor(model => model.HelpDeskCalls, ViewData["currCalls"] as IEnumerable<SelectListItem>, new { size = "12"}) %>
<%: Html.ListBox("Model.HelpDeskCalls", new MultiSelectList(Model.HelpDeskCalls, "ID", "CallTitle", (IEnumerable)ViewData["currSelected"]), new { size = "12"}) %>
<%: Html.ValidationMessageFor(model => model.HelpDeskCalls) %>
</div>
对于这个示例,我只是选择偶然的HelpDeskCall.IDs。我正在为ListBoxFor尝试两种不同的语法:一种使用IEnumerable值进行选择,一种使用IEnumerable的SelectListItems。默认情况下,当我运行此代码时,不会对ListBoxFor进行任何选择,但非强类型ListBox会正确选择。
我在ASP上阅读this post,在SO上阅读this thread,但没有快乐。实际上,如果我将覆盖ToString()添加到我的HelpDeskCall类(如ASP.net线程中所建议的那样),则会选择所有值,这也不正确。
如果有人可以阐明这应该如何运作(以及我错过或做错了什么),那么新手将非常感激。
答案 0 :(得分:91)
以下是一个说明强类型版本的示例:
型号:
public class MyViewModel
{
public int[] SelectedItemIds { get; set; }
public MultiSelectList Items { get; set; }
}
控制器:
public class HomeController : Controller
{
public ActionResult Index()
{
// Preselect items with id 1 and 3
var selectedItemIds = new[] { 1, 3 };
var model = new MyViewModel
{
Items = new MultiSelectList(
new[]
{
// TODO: Fetch from your repository
new { Id = 1, Name = "item 1" },
new { Id = 2, Name = "item 2" },
new { Id = 3, Name = "item 3" },
},
"Id",
"Name",
selectedItemIds
)
};
return View(model);
}
}
查看:
<%: Html.ListBoxFor(x => x.SelectedItemIds, Model.Items) %>
答案 1 :(得分:8)
我不知道在我正在使用的MVC3的RTM中是否已经改变了这种行为,但是现在看来选择和绑定是开箱即用的。唯一的问题是模型应该包含具有ID的属性,如:
public class MyViewModel {
public int[] ItemIDs { get; set; }
}
然后视图中的以下内容可以正常工作,既可以预先选择正确的值,也可以在发布过程中正确绑定:
@Html.ListBoxFor(model => model.ItemIDs, (IEnumerable<SelectListItem>)(new[] {
new SelectListItem() { Value = "1", Text = "1" },
new SelectListItem() { Value = "2", Text = "2" }
}))
答案 2 :(得分:2)
我找到了更好的解决方法。通常的方式来预选选择列表:
@Html.ListBoxFor(
model => model.Roles,
new MultiSelectList(db.Roles, "Id", "Name")
)
@Html.ValidationMessageFor(model => model.Roles)
不起作用..,从未选择任何选项,直到:
public ActionResult Edit(int id)
{
var user = db.Users.Find(id);
// this is workaround for http://aspnet.codeplex.com/workitem/4932?ProjectName=aspnet
ViewData["Roles"] = user.Roles.Select(r => r.Id);
return View(user);
}
选定的角色必须存储在ViewData中,以解决令人讨厌的错误。
答案 3 :(得分:0)
另一个选择是利用nameof,您可以执行以下操作;
Html.ListBox(nameof(MainProjectViewModel.Projects), Model.Projects)