MVC Multiple DropDownLists from 1 List<SelectListItem>
Asked Answered
H

4

11

Background: I have 4 dropdown lists on my page that all use one List of SelectListItem to pull data from. All 4 of these dropdowns will always have the same exact elements in them. Each dropdown has an empty element at the top.

Problem: If I do not select an item from the list that renders 2nd, when the page loads the 2nd list automatically selects the item that is selected in the 1st list. This is because (I think) the list has a SelectListItem where Selected = true, and it just uses that one in the second list.

Is there any way to use one list source for multiple dropdown lists? I don't want to duplicate this list 4 times unless I absolutely 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)
Homonym answered 18/9, 2013 at 19:28 Comment(0)
A
5

In your list, need to create different SelectList entities for each of the four drop down lists like so:

@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 correspond to your value and text elements of the drop down options.

Apathetic answered 18/9, 2013 at 19:45 Comment(2)
While doing that won't hurt anything, it's not required, and isn't the source of the problem.Solution
6 years later, you're still saving lives! It might be related to the fact that Model.PossibleItems is already a collection of SelectListItem, the SelectListItem.Selected boolean is then shared between those DropDownListFor.Merino
L
5

2 years ago but for anyone who finds this like I did looking for answers Feussy's comment above is the way to go. I'll try to explain why and what I found.

Using the OP example above. A couple conditions must be met in order to see the described behavior.

  • x.SelectedItem1 should have a value (say 1).
  • x.SelectedItem2 must be NULL. (if it is not a nullable type and just say an INT it 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 to the next line. Now if you look at Model.PossibleItems you will see that Html.DropDownListFor has modified your selectlist on the Model rather than just using it! The option for x.SelectedItem1 now has a 'selected' attribute not only in the HTML that goes to the client but in your model as well! This seems like bad behavior on Html.DropDownListFor but it definitely does it.

Now when you hit @Html.DropDownListFor(x => x.SelectedItem2, Model.PossibleItems)

  • If x.SelectedItem2 has a value it will set it and you will be fine but....
  • If x.SelectedItem2 is null, the second @Html.DropDownListFor just seems to take the altered(by the first DropDownListFor) selectlist as is and your second drop down will have x.SelectedItem1 selected. (because the selectlist itself was altered)

Feussy's answer works because instead of having one selectList on the model that gets reused it is creating separate selectLists that are generated from some List/IEnumerable on the model that gets reused instead.

So the moral of the story is don't reuse a selectList with nullable values because Html.DropDownListFor has no problems altering the thing and won't clear out any selected attributes if the value is NULL.

Hope that was clear.

Leiker answered 20/11, 2015 at 0:34 Comment(0)
J
3

Instead of using a List<SelectListItem>, use a 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)
Josefinejoseito answered 15/12, 2017 at 14:13 Comment(0)
S
0

The code you currently have is the best way to do it, and it should work just as it is. SelectListItem does have a Selected property, but this is most usually set by a SelectList instance. Otherwise, you'd have to manually set this property somewhere on your own. Since you're using IEnumerable<SelectListItem> instead of an instantiated SelectList, all of the items should default to having Selected as false. It's only when Razor renders the DropDownListFor control does you enumerable get turned into an actual SelectList and have its selected value set based on the model. Check your other code and make sure you're not setting the selected status manually anywhere.

FWIW, you don't need to add an empty item manually: the DropDownListFor control has a means to add an empty item to the list.

@Html.DropDownListFor(x => x.SelectedItem1, Model.PossibleItems, string.Empty)
Solution answered 18/9, 2013 at 19:46 Comment(3)
I'm not setting the selected value anywhere else, and the solution I have above was not working so I went with seperate lists for each dropdown. Unfortunately its not the cleanest solution, but it's working for now.Homonym
I am facing the same problem. I agree that it should work. But @Homonym is right. Something is wrong here. See this question on asp.net forums and this question on stackoverflow for unsatisfactory responses.Flimsy
The only thing I can think of a possible cause is that the conversion of Model.PossibleItems into a true blue SelectList is perhaps being cached and used for each drop down, since they all use the same thing. What happens if you just duplicate the drop down choices into another property and use that for one of the drop downs? Does the same behavior occur?Solution

© 2022 - 2024 — McMap. All rights reserved.