1

I'm creating a SelectList to pass to a Html.DropDownList, but the correct value doesn't seem to be populating

var x = new SelectList(new[] { 
    new SelectListItem() { Value="1", Text="Vanilla"}, 
    new SelectListItem() { Value="2", Text="Chocolate"},
    new SelectListItem() { Value="3", Text="Strawberry"}
}, "Value", "Text", "2");

SelectList should take a constructor that takes in the selectedValue:

public SelectList(
    IEnumerable items,
    string dataValueField,
    string dataTextField,
    object selectedValue
)

But this only sets the SelectedValue on the entire collection. The individual SelectListItems haven't been set as Selected

Inspector

Do I need to iterate over them individually and set selected for each as in this question?

KyleMit
  • 30,350
  • 66
  • 462
  • 664
  • Have you tried adding `, Selected=true` to the `SelectListItem` that you want selected? – itsme86 Dec 05 '17 at 20:51
  • @itsme86, this is a simplified example just for full transparency of the values going into the select list. In my actual codebase those are being pulled in externally. I could iterate through them and set the selected property manually, but it seems like passing in the selected value when creating the `SelectList` would do that automatically. Further, if the selected value on item value isn't set, the dropdown doesn't populate with an initial value. – KyleMit Dec 05 '17 at 20:55
  • Creating a new identical `IEnumerable` from the first one by using `new SelectList()` is just pointless extra overhead. And setting the `Selected` property is ignored when you binding to a property (its the value of the property that determines what is selected) –  Dec 05 '17 at 20:57
  • And your looking at the `items` property and you have not set the `Selected = true"` on any of those), not the `IEnumerable` that is the result of that method. –  Dec 05 '17 at 21:01
  • @StephenMuecke, ahh, okay, I was trying to be clever. Instead of passing the `SelectList` over a ViewModel, I created a `LookupProperty` class that just takes in a `Value` and a `SelectList`. Then the property on my model has that class. The problem is, when I create a `EditorFor(MyProp.Value)` the model binder works happily, but I don't get any of the data validation attributes on `MyProp`. I was trying to use `EditorFor(MyProp)` which brings over the validation attributes. I added a ModelBinder to new up MyProp -> MyProp.Value, but then needed to render the class and point to the `Value` – KyleMit Dec 05 '17 at 21:07
  • Sorry, not sure I understand your last comment and what your trying to achieve. But for a bit more understanding of how to set the selected value, refer [this answer](https://stackoverflow.com/questions/41719293/mvc5-how-to-set-selectedvalue-in-dropdownlistfor-html-helper/41731685#41731685) –  Dec 05 '17 at 21:10
  • And if you have a look at the value of `x` then you will see that the 2nd `SelectListItem` has `Selected=true` (but as noted before, its ignored anyway unless your not binding to anything) –  Dec 05 '17 at 21:16

1 Answers1

3

The Selected property is being set by the SelectList constructor. The image you have shown is for the items argument (i.e the collection of SelectListItem that you passing to the method), not the result of calling the method.

The constructor does not modify the collection passed to it, it creates a new IEnumerable<SelectListItem>, and if you inspect the value of var x, then you will see that the 2nd SelectListItem (the one with Value = "2") will have its Selected property set to true.

However, the purpose of the SelectListItem class is for use in one of the HtmlHelper methods that generates a <select> (DropDownList(), DropDownListFor(), ListBox() and ListBoxFor() methods) which accept an IEnumerable<SelectListItem> as either the 1st or 2nd argument.

Unless you specifically not binding to a model property (e.g. @Html.DropDownList("NotAModelProperty", Model.YourSelectList)), then setting the Selected property is ignored because the method sets the selected option based on the value of the property your binding to (refer How to set “selectedValue” in DropDownListFor Html helper for more detail), therefore creating a new IEnumerable<SelectListItem> from the first one by using new SelectList(...) is pointless extra overhead.

The reason for using the SelectList constructor is to create an IEnumerable<SelectListItem> from an existing collection of objects, for example

IEnumerable<SelectListItem> options = new SelectList(db.Flavors, "ID", "Name")

which would get the records from the Flavors table, and set the Value based on its ID property, and the Text based on its Name property. It just provides an alternative to using (say)

IEnumerable<SelectListItem> options = db.Flavors.Select(x => new SelectListItem
{
    Value = x.ID.ToString(),
    Text = x.Name
});