Проблемы с выбором значений в ListBoxFor
Это мой первый вопрос, и он, вероятно, плохой, поэтому, пожалуйста, будьте осторожны.
Недавно работая над моим первым веб-приложением ASP.Net MVC2, я столкнулся с некоторыми проблемами, когда мне нужно было выбрать несколько значений в списке. Я работал над ним с помощью некоторого jQuery, но пошел вперед и собрал очень простой код для демонстрации. Я использую EF для модели с двумя объектами - Клиентами и 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.ID, которые являются четными. Я пытаюсь использовать два разных синтаксиса для ListBoxFor: One использует IEnumerable значений для выбора, используя IEnumerable из SelectListItems. По умолчанию, когда я запускаю этот код, в ListBoxFor не выбираются, но не строго типизированный ListBox правильно выбирает.
Я прочитал этот пост на ASP.Net и этот поток на SO, но никакой радости. На самом деле, если я добавлю переопределить ToString() в мой класс HelpDeskCall (как это предложено в потоке ASP.net), все значения будут выбраны, что тоже неверно.
Если кто-то может пролить свет на то, как это должно работать (и чего я упускаю или делаю неправильно), этот неофит был бы очень благодарен.
Джон
Ответы
Ответ 1
Вот пример, иллюстрирующий строго типизированную версию:
Модель:
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) %>
Ответ 2
Я не знаю, изменилось ли это поведение в RTM MVC3, который я использую, но кажется, что выбор и привязка теперь работают из коробки. Единственный улов в том, что модель должна содержать свойство с идентификаторами, например:
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" }
}))
Ответ 3
Я нашел лучшее обходное решение. Обычный способ предварительного выбора списка выбора:
@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, чтобы обходиться неприятная ошибка.