MVC Multiple DropDownLists from 1 List <SelectListItem>
Background: I have 4 drop-down lists on my page that use one SelectListItem to retrieve data. All 4 of these drop-down lists will always have the same exact elements. Each drop-down list has an empty item at the top.
Problem: If I do not select an item from the list that displays the 2nd, when the page loads the second list, it automatically selects the item selected in the 1st list. This is because (I think) the list has SelectListItem where Selected = true , and it just uses it in the second list.
Can I use a single list source for multiple drop-down lists? I do not want to duplicate this list 4 times, if I do not have to ...
Code
//this is the list source public IEnumerable<SelectListItem> PossibleItems { get; set; } //this is the code on my .cshtml page @Html.DropDownListFor(x => x.SelectedItem1, Model.PossibleItems) @Html.DropDownListFor(x => x.SelectedItem2, Model.PossibleItems) @Html.DropDownListFor(x => x.SelectedItem3, Model.PossibleItems) @Html.DropDownListFor(x => x.SelectedItem4, Model.PossibleItems) 2 years ago, but for those who find it, as if I was looking for answers. Feussy's story above is the way to go. I will try to explain why and what I found.
Use the OP example above. To see the described behavior, you must fulfill a couple of conditions.
- x.SelectedItem1 must have a value (say 1).
- x.SelectedItem2 must be NULL. (if it is not a null type and just say that INT will default to 0 and you won't see the behavior)
Put a breakpoint at @Html.DropDownListFor(x => x.SelectedItem1, Model.PossibleItems)
If you look in Model.PossibleItems, you will see the list as expected. Let the code continue the next line. Now, if you look at Model.PossibleItems, you will see that Html.DropDownListFor changed your selectlist to a model, and not just used it! The option for x.SelectedItem1 now has the 'selected' attribute not only in the HTML that goes to the client, but also in your model! This seems like bad behavior on Html.DropDownListFor, but it definitely does.
Now when you click @Html.DropDownListFor(x => x.SelectedItem2, Model.PossibleItems)
- If x.SelectedItem2 matters, it will be installed and you will be fine but ....
- If x.SelectedItem2 is null, the second @ Html.DropDownListFor just seems to have changed (by the first DropDownListFor) selectlist as your second snapshot will select x.SelectedItem1. (because the favorites list itself has been changed)
Feussy's answer works because instead of having one selectList in a model that is being reused, it creates separate selectLists that are generated from some List / IEnumerable on the model that is being reused.
So, the moral of this story does not repeat the use of selectList with null values, because Html.DropDownListFor has no problem changing things and will not remove any selected attributes if the value is NULL.
Hope this was clear.
In your list, you need to create different SelectList objects for each of the four drop-down lists, for example:
@Html.DropDownListFor(x => x.SelectedItem1, new SelectList(Model.PossibleItems, "dataValue", "textValue", Model.SelectedItem1)) @Html.DropDownListFor(x => x.SelectedItem2, Model.PossibleItems) new SelectList(Model.PossibleItems, "dataValue", "textValue", Model.SelectedItem2)) @Html.DropDownListFor(x => x.SelectedItem3, Model.PossibleItems) new SelectList(Model.PossibleItems, "dataValue", "textValue", Model.SelectedItem3)) @Html.DropDownListFor(x => x.SelectedItem4, Model.PossibleItems) new SelectList(Model.PossibleItems, "dataValue", "textValue", Model.SelectedItem4)) In this example, "dataValue" and "textValue" are the properties of the SelectListItem object that match your values ββand the text elements of the dropdown parameters.
The code you have is the best way to do this, and it should work as it is. SelectListItem has the Selected property, but most often this is set by the SelectList instance. Otherwise, you will have to manually set this property somewhere yourself. Since you are using IEnumerable<SelectListItem> instead of a SelectList instance, all elements must be Selected as false. Only when Razor displays the DropDownListFor control will you list it, turn into the actual SelectList and set its selected value based on the model. Check your other code and make sure you are not setting the selected state manually anywhere.
FWIW, you donβt need to add an empty element manually: the DropDownListFor control has a tool for adding an empty element to the list.
@Html.DropDownListFor(x => x.SelectedItem1, Model.PossibleItems, string.Empty) Instead of using List<SelectListItem> use SelectList . Then you can reuse the list of items in DropDownListFor .
Model:
public SelectList PossibleItems { get; set; } Controller:
var items = new List<SelectListItem>(); model.PossibleItems = new SelectList(items, "Value", "Text"); View:
@Html.DropDownListFor(m => m.Item1, Model.PossibleItems) @Html.DropDownListFor(m => m.Item2, Model.PossibleItems)