Reputation: 6605
In the view, I have
<div class="form-group">
<div>
@Html.LabelFor(m => m.DoctorList, new { @class = "control-label" })
</div>
<div>
@Html.ListBoxFor(m => m.DoctorList, new MultiSelectList((List<SelectListItem>)ViewBag.DoctorList, "Value", "Text", ((List<string>)(ViewBag.DoctorsSelected)).ToArray()), new {style="display:block;height:20.0em;", @class = "form-control", Multiple = "multiple"})
</div>
</div>
DoctorList is a list in model, ViewBag.DoctorList is the entire list of doctors, they are something similar to:
public static List<SelectListItem> GetDoctorList()
{
List<SelectListItem> ret = new List<SelectListItem>();
// load doctors from database
// for now, fake data
for (int k = 1; k <= 30; k++)
{
string n = "Doctor" + k.ToString();
ret.Add(new SelectListItem() { Value = n, Text = n });
}
return ret;
}
ViewBag.DoctorsSelected is a List, which is a list of doctor names, something similar to:
List<string> doctorsSelected = new List<string>();
doctorsSelected.Add("Doctor1");
doctorsSelected.Add("Doctor5");
What I want to do is that preselect the doctors in the listbox. However, it always shows the listbox, but no reselection.
I also tried to use below in GetDoctorList()
ret.Add(new SelectListItem() { Value = n, Text = n, Select = true });
Still no preselection.
Anyone knows how to do it? I'm using MVC4.
Thanks
Upvotes: 0
Views: 563
Reputation:
You cannot use the same name for the property your binding to and the SelectList
. Your model should have a property (say)
public IEnumerable<string> SelectedDoctors { get; set; }
and the view will be
@Html.ListBoxFor(m => m.SelectedDoctors, (IEnumerable<SelectListItem>)ViewBag.DoctorList)
If SelectedDoctors
contains values that match the values in the SelectList
, then those items will be selected when the view is rendered. For example in the controller,
model.SelectedDoctors = new List<string> { "Doctor1", "Doctor5" };
return View(model);
Note also that ViewBag.DoctorList
is already IEnumerable<SelectListItem>
so its just pointless extra overhead to create an identical new IEnumerable<SelectListItem>
from it using new SelectList()
in your view.
Edit (in response to OP query as to why the names must be different)
The way the ListBoxFor()
works is
ViewDataDictionary
(in your case the item in the
ViewDataDictionary
is List<SelectListItem>
).IEnumerable<SelectListItem>
from the SelectList
provided in the second parameter (in order to set the Selected
property of each SelectListItem
based on the values your binding
to).<option>
element based on the Value
,
Text
and Selected
properties of each SelectListItem
.In your case, as each SelectListItem
is created, its checks if any values in the property your binding to match the Value
property of the SelectList
, but your values are "System.Web.Mvc.SelectListItem"
(they are complex objects so the .ToString()
value of the object is used) and none of your SelectListItems
have a value of "System.Web.Mvc.SelectListItem"
(just "Doctor1
", "Doctor2"
etc.) so the Selected
property is false
and consequently, none of the <option>
elements have the selected="selected"
attribute set.
The above is a simplified explanation and if your want to see how it all works, you can view/download the source code here.
Upvotes: 2