32

In my view

<%= Html.DropDownListFor( x => x.Countries[ i ], Model.CountryList )%>

in my controller

public int[ ] Countries { get; set; }

public List<SelectListItem> CountryList { get; set; }

When the forms gets posted there is no problem, the dropdown is populated and the values the user selects are posted. But when I try to load the form with already assigned values to the Countries[ ] it does not get selected.

Craig McKeachie
  • 1,704
  • 1
  • 21
  • 25
Eyeslandic
  • 14,553
  • 13
  • 41
  • 54

6 Answers6

32

Not sure if this is new to mv4 or if it exists in prior version. But the DropDownListFor includes an additional parameter for the SelectList Constructor.

SelectList(IEnumerable, String, String, Object)

For example:

Html.DropDownListFor( x => x.Countries[ i ], New SelectList(Model.CountryList,"ID","Description",Model.Countries[i]))

Where ID is the Country ID in the CountryList object and Description is the Country Name.

Cezar
  • 55,636
  • 19
  • 86
  • 87
Nick
  • 329
  • 3
  • 2
  • 1
    +1 for getting it to work for me. I still don't want to recreate my SelectList for every element in my loop though, so I'm gonna keep searching. – iGanja Apr 12 '13 at 20:46
  • 4
    Thanks! Worked well for me, to display a dropdown (Location Id) in each row of a table. `@Html.DropDownListFor(x=>x.OrderLineItems[i].OrderMfgLocationId, new SelectList(Model.MfgLocations, "Value", "Text", Model.OrderLineItems[i].OrderMfgLocationId))` – Krishna Gupta Nov 09 '15 at 23:29
  • 1
    doesnt select the matching item in list - adds new item to top of list. usable, but not ideal. – nothingisnecessary Mar 02 '17 at 23:12
10

I'm getting the same too. When using foreach to loop around a DropDownListFor (i.e. to render multiple select elements on a page).

My work around is to set the selected value in the controller rather than the view: something like this:

In the controller:

public class FruitList 
{        
    public int? selectedFruit{ get; set; }
    public List<SelectListItem> fruits
    {
        get
        {
            fruitEntities F = new fruitEntities();
            List<SelectListItem> list = (from o in F.Options
                                         select new SelectListItem
                                         {
                                             Value = o.fruitID,
                                             Text = o.fruit,                                                 
                                             Selected = o.fruitID == selectedFruit
                                         }).ToList();
            return list;
        }
    }
}

public class ViewModel 
{              
    public List<FruitList> collectionOfFruitLists { get; set; }        
}

In the view

<table>                        
   <% for (int i=0; i < Model.collectionOfFruitLists.Count; i++ )
        { %>
        <tr>                            
            <td><%: Html.DropDownList("fruitSelectList", collectionOfFruitLists[i].fruits, "Please select...") %></td>                
        </tr>
        <%} %>
 </table>

The nifty bit is Selected = o.fruitID == selectedFruit in the controller which acts like a SQL CASE statement; this is really well explained by Lance Fisher (thanks Lance, your post really helped me out :)

phs
  • 10,687
  • 4
  • 58
  • 84
Neil Billingham
  • 2,235
  • 4
  • 23
  • 34
  • You don't need the `? true : false` bit, just `Selected = o.fruitID == selectedFruit` will do. – enashnash Jun 14 '11 at 12:34
  • 1
    Mr B - good solution man. I get a StackOverflow error when I run your code, but the idea is sound - you have to create the SelectList for each dropdown and explicitly set the SelectedItem in the Controller. Nice work. This was driving me nuts! – Chris Holmes Nov 12 '11 at 19:30
  • 3
    Just want to say that as of today (2016ish) with MVC5, this is still an issue... This is one of those "But why??" that get lost in the universe, when logically you'd think it should work but just doesn't for no apparent reason. You'd think Microsoft would say a "By the way", but just doesn't either.. Thank you stackoverflow!! I will try to resolve myself to do it this way... ughhh – user627283 Mar 22 '16 at 20:11
9

I know this question is a bit old but I just came across this problem with looping through a list of objects and attempting to bind the values to DropDownListFor(s) in my Edit View.

I overcame the issue with an inline solution by using the logic from some of the previous solutions given by others for this question.

Binding to my Model:

@Html.DropDownListFor(model => model.QuestionActions[i].QuestionActionTypeId,
      Model.QuestionActionTypes.Select(x => new SelectListItem() { Value = x.Value, Text = x.Text, Selected = (x.Value == Model.QuestionActions[i].QuestionActionTypeId.ToString()) }).ToList(),
          "Select Action Type",
                 new { })

Model.QuestionActionTypes is a SelectList that is populated in my Controller.

Kevin Dark
  • 458
  • 5
  • 15
0

This is a bit of a hack, and JavaScript reliant but it worked very well for me.

You'll need to know the client IDs that will be produced by the fields (usually these can be worked out manually but for safety you may want to use something like a FieldIDFor method.

You just need to set the values based on the model, in jQuery's $(document).ready:

<script type="text/javascript">
    $(document).ready(function () {
        @for(var i = 0; i < 5; i++)
        {
            <text>
                $("#@Html.FieldIDFor(m => m.Countries[i])").val("@Model.Countries[i]");
            </text>
        }
    });
</script>
rashleighp
  • 1,226
  • 1
  • 13
  • 21
-1

A select box sends a single value, so the Countries property should not be an array. Also in your post it is not clear where's the i variable you are using in your lambda expression coming from and this x.CountryList used in the helper won't compile as x is not defined.

Model:

public class MyModel
{
    public int SelectedCountry { get; set; }
    public List<SelectListItem> CountryList { get; set; }
}

View:

<%= Html.DropDownListFor(x => x.SelectedCountry, Model.CountryList) %>

UPDATE:

According to the comment it seems that there are multiple drop downs. I suspect that the problem might come from the i variable used as index in a for loop.

You might try this instead:

Model:

public class MyModel
{
    public int[] Countries { get; set; }
    public List<SelectListItem> CountryList { get; set; }
}

View:

<% foreach (var country in Model.Countries) { %>
    <%= Html.DropDownListFor(x => country, Model.CountryList) %>
<% } %>
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • The "i" is not the problem I think, because when I post the form the values from the dropdowns are posted correctly into the Countries[] property. – Eyeslandic Apr 13 '10 at 17:46
  • "i" is necessary for those of us who are posting back the results, and need the collection to bind on the server. – iGanja Apr 12 '13 at 20:49
-1

Instead of using a IEnumerable in your viewmodel use a List of objects like this one:

public List<PairVM<string,string>> TiposValorCobertura { get; private set; }

And in your view when you assign the selectable elements for the dropdownlist in the loop, do it this way:

@Html.DropDownListFor(m => m.Coberturas[i].TipoLimiteInferior, new SelectList(Model.TiposValorCobertura,"Key","Description",  Model.Coberturas[i].TipoLimiteIferior))

Where "Key" and "Description" are PairVM's properties

FelixSFD
  • 6,052
  • 10
  • 43
  • 117