ASP.NET MVC DropDownListFor does not honour SelectListItem.Selected
Asked Answered
M

4

7

I am using DropDownListFor to render a dropdown list in a view. Somehow the rendered list does not select the SelectListItem with Selected set to true.

In the controller action:

var selectList = sortedEntries.Select(entry => new SelectListItem
                            {
                                Selected = entry.Value.Equals(selectedValue),
                                Text = entry.Value,
                                Value = entry.Id
                            });

return View(new DropDownListModel
            {
                ListId = id,
                SelectList = selectList,
                OptionLabel = "Click to Select"
            });

In the view:

<%= Html.DropDownListFor(m => m.ListId, 
    Model.SelectList, 
    Model.OptionLabel, 
    new {@class="someClass"}) %>

I have tried the following:

  1. make sure that there is one and only one items with Selected set to true.
  2. remove the option label argument.
  3. remove the HTML attribute object.
  4. use SelectList in DropDownListFor:

   Html.DropDownListFor(m => m.ListId, 
        new SelectList(Model.SelectList, "Value", "Text", 
             new List<SelectListItem>(Model.SelectList).Find(s => s.Selected)), 
        new {@class="someClass"})

Any suggestions as to what went wrong?

EDIT:

more information:

  • This action is a child action, called by another view with HTML.RenderAction
Manara answered 14/7, 2011 at 6:54 Comment(0)
D
3

Try like this:

var selectList = sortedEntries.Select(entry => new SelectListItem
{
    Text = entry.Value,
    Value = entry.Id
});

return View(new DropDownListModel
{
    // The drop down list is bound to ListId so simply set its value
    // to some element value in the list and it will get automatically
    // preselected
    ListId = selectedValue, 
    SelectList = selectList,
    OptionLabel = "Click to Select"
});

and in the view:

<%= Html.DropDownListFor(
    m => m.ListId, 
    new SelectList(Model.SelectList, "Value", "Text"), 
    Model.OptionLabel, 
    new { @class = "someClass" }
) %>

There could be one more gotcha: you are trying to change the selected value in a POST action. For example you rendered a form, the user selected some value in the dropdown, submitted the form and in your POST action you do some processing on this selected value and when you redisplay the view you want the drop down list to have some other value selected. In this case you will have to remove the initial selection which is contained in the ModelState or the Html helper will ignore the selected value in the model:

// do this before returning the view and only if your scenario
// corresponds to what I described above
ModelState.Remove("ListId");
Dugald answered 14/7, 2011 at 7:55 Comment(0)
I
6

DropDownListFor will always select the value that the listbox is for, so in this case it will look at the value of ListId and make that item in the list selected. If ListId is not found in the list, the first item (or default text) will be selected. If you want a list that selects based on the selected attribute use DropDownList (without the For, in that case you have to name it yourself).

So in your case this would work:

var selectList = sortedEntries.Select(entry => new SelectListItem
{
    Text = entry.Value,
    Value = entry.Id
});

return View(new DropDownListModel
{
    ListId = selectedValue,
    SelectList = selectList,
    OptionLabel = "Click to Select"
});
Implode answered 14/7, 2011 at 10:30 Comment(1)
I ended up using DropDownList, which allows me to specify an ID for the select control, as well as a selected value in the SelectListItem. Thanks for the explanation!Manara
O
5

I got the same problem on the same model (with the other models in the decision no problem)

Does not work:

@Html.DropDownListFor(o => o.Drivers.ValueListItems.Value, Model.Drivers.ValueListItems, new { size = Model.Drivers.ValueSizeList, Multiple = "multiple" })

Works perfectly, the elements selected:

@Html.DropDownListFor(o => o.Drivers.ValueListItems.ToDictionary(u=>u.Value).Values, Model.Drivers.ValueListItems, new { size = Model.Drivers.ValueSizeList, Multiple = "multiple" })
Ornamentation answered 13/9, 2012 at 17:42 Comment(1)
The only problem with this is that the name of the control will now be "Values".Filippo
D
3

Try like this:

var selectList = sortedEntries.Select(entry => new SelectListItem
{
    Text = entry.Value,
    Value = entry.Id
});

return View(new DropDownListModel
{
    // The drop down list is bound to ListId so simply set its value
    // to some element value in the list and it will get automatically
    // preselected
    ListId = selectedValue, 
    SelectList = selectList,
    OptionLabel = "Click to Select"
});

and in the view:

<%= Html.DropDownListFor(
    m => m.ListId, 
    new SelectList(Model.SelectList, "Value", "Text"), 
    Model.OptionLabel, 
    new { @class = "someClass" }
) %>

There could be one more gotcha: you are trying to change the selected value in a POST action. For example you rendered a form, the user selected some value in the dropdown, submitted the form and in your POST action you do some processing on this selected value and when you redisplay the view you want the drop down list to have some other value selected. In this case you will have to remove the initial selection which is contained in the ModelState or the Html helper will ignore the selected value in the model:

// do this before returning the view and only if your scenario
// corresponds to what I described above
ModelState.Remove("ListId");
Dugald answered 14/7, 2011 at 7:55 Comment(0)
U
0

The solution for this problem is simpler that we all think...

All we need to do is set the property on the view model for the element that the dropdown is bound to - i.e: ListId = 3 for example

this way when we do this

Html.DropDownListFor(m => m.ListId, 
    new SelectList(Model.SelectList, "Value", "Text", 
         new List<SelectListItem>(Model.SelectList).Find(s => s.Selected)), 
    new {@class="someClass"})

the HtmlHelper will automatically pick up the default value to display on the DropDownList

simples!

Hope it may help you and all the others - like me! - that have lost a lot of time searching for a solution for this apparent issue.

Unabridged answered 1/7, 2014 at 10:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.