14

I have read through this question ASP.NET MVC DropDownListFor not selecting value from model and answer but I don't know the solution to my problem.

This is my view:

@foreach (var adjusterLanguages in Model.adjusterLanguages)
{
    <div class="editor-field row">
        @Html.DropDownListFor(model => Model.adjusterLanguages[i].languageID,
                              (SelectList)ViewBag.ForeignLanguages) 
        @Html.ValidationMessageFor(model =>Model.adjusterLanguages[i].languageID)
    </div>

    <div style="clear: left;"></div>

    i++;
}

I can confirm that the model data is being populated (from my controller):

model.adjusterLanguages = adjLangs;

So, how can I make it select the items when the model gets sent to the view?

The generated html is as follows:

<div class="editor-field row">
    <select id="adjusterLanguages_0__languageID" name="adjusterLanguages[0].languageID"><option value="">--Select--
        </option>
        <option value="94c5be88-814e-4719-9784-587eb88aa975">Afrikanns</option>
        <option value="37b7bf71-7f4e-47c2-8b81-652b0d63dbcb">Albanian</option>
        <option value="c94d6d85-0ba2-47d7-932e-2a61feba37b3">Arabic</option>
        <!-- ... truncated for brevity ... -->
    </select> 
    <span class="field-validation-valid" data-valmsg-for="adjusterLanguages[0].languageID" data-valmsg-replace="true"></span>
</div>
<div style="clear: left;"></div>
<div class="editor-field row">
     <select id="adjusterLanguages_1__languageID" name="adjusterLanguages[1].languageID">
          <option value="">--Select--</option>
          <option value="94c5be88-814e-4719-9784-587eb88aa975">Afrikanns</option>
          <option value="37b7bf71-7f4e-47c2-8b81-652b0d63dbcb">Albanian</option>
          <option value="c94d6d85-0ba2-47d7-932e-2a61feba37b3">Arabic</option>
          <!-- ... truncated for brevity ... -->
     </select> 
     <span class="field-validation-valid" data-valmsg-for="adjusterLanguages[1].languageID" data-valmsg-replace="true"></span>
</div>
Community
  • 1
  • 1
user1477388
  • 20,790
  • 32
  • 144
  • 264
  • What is the HTML that is generated from the above code? – Matt Houser May 28 '13 at 19:11
  • Do any of your ` – Matt Houser May 28 '13 at 19:16
  • Also, what if you "print out" each of your languageID values, is it as you expect? – Matt Houser May 28 '13 at 19:17
  • 1
    @MattHouser None of the elements have `selected`. Your second question is good. When I output the value of `@Model.adjusterLanguages[i].languageID`, it gives me what I expect (a GUID like c94d6d85-0ba2-47d7-932e-2a61feba37b3). – user1477388 May 28 '13 at 19:18
  • Strange names... Does the controller receive a model that contains the fields `adjusterLanguage_0__LanguageID` and `adjusterLanguage_1__languageID`? And you send the form back to the controller with post? And all that kind of basic things? The problem is probably not in this part of the code but somewhere else. – Albert May 28 '13 at 19:19
  • The question you linked at the top seems to tell you what the problem is, no? `The following is not supported: m => m.ShippingTypes[i].RequiredShippingTypeId. It works only with simple property access expressions but not with indexed collection access.` – Colm Prunty May 28 '13 at 19:21
  • @ColmPrunty Yes, but I don't know how to solve it. What can I do to make the values be selected? – user1477388 May 28 '13 at 19:21

6 Answers6

39

I found the answer! Thanks to all for your help. When I change my code to the following, it works. The code simply specifies the selected value:

@Html.DropDownListFor(
   model => Model.adjusterLanguages[i].languageID, 
   new SelectList(
       ViewBag.ForeignLanguages, "Value", "Text", 
       @Model.adjusterLanguages[i].languageID)) 
serhio
  • 28,010
  • 62
  • 221
  • 374
user1477388
  • 20,790
  • 32
  • 144
  • 264
  • Thanks for the solution. I don't understand why it doesn't select the correct value though, maybe it's not supposed to? Weird... – Luke Dec 10 '14 at 18:07
  • Thanks. you saved our time. But if its a multi selectable drop-down and languageID is LIst then its not working. – Kartheek Feb 13 '15 at 12:35
  • 1
    I was having the same issue. Once I updated to use an actual object from the list in the first argument to the constructor for SelectList as the selected item, I noticed the HTML was generating an tag in my dropdowns, but the browser wasn't respecting it. Turned out, I just needed to fully reload the page. The browser was remembering the incorrect 'selections' between page refreshes. Tripped me up for a sec! Hope this saves someone the troubs. – K0D4 Dec 09 '15 at 19:47
  • Thanks. Last argument of SelectList(ViewBag.ForeignLanguages, "Value", "Text", @Model.adjusterLanguages[i].languageID)) is the key. – Avadhani Mar 31 '20 at 07:31
  • 1
    I found this helpful when wanting to reuse a dropdown list for multiple dropdowns with different selected values. – Wildcat Matt Apr 21 '21 at 19:25
4

When you're populating ViewBag.ForeignLanguages in the controller, on the item that should be selected, set the .Selected property to true.

However, you'll have an issue with this because you have many items using the same ForeignLangauges list of items.

You'll need to create one list for each adjusterLanguages in your list. They cannot share the same list because adjusterLanguages[0] needs a different item selected than adjusterLanaguages[1]

Edit:

I like this model:

public class AdjusterLanguageModel
{
  public Guid LanguageId { get; set; }
  List<SelectListItem> ForeignLanguages{ get; set; }
}

public class AdjusterListModel
{
  public List<AdjusterLanguageModel> AdjusterLanguages { get; set }
}

In the controller, you populate your list with an ID and it's own list of available languages.

In your view:

@foreach (var adjusterLanguages in Model.AdjusterLanguages)
{
    <div class="editor-field row">
        @Html.DropDownListFor(model => adjusterLanguages[i].LanguageID,
          adjusterLanguages[i].ForeignLanguages) 
        @Html.ValidationMessageFor(model => adjusterLanguages[i].LanguageID)
    </div>

    <div style="clear: left;"></div>

    i++;
}

So each DropDownListFor get's it's own list of languages.

Matt Houser
  • 33,983
  • 6
  • 70
  • 88
  • But, the selected item value is already in the model. Shouldn't MVC simply select the item from the list? Is there an override to make it do so? – user1477388 May 28 '13 at 19:25
  • It should, but it's not. The override is for you to set the `.Selected` property to be true in the controller. – Matt Houser May 28 '13 at 19:27
  • Thanks, Matt. Please see the answer that I just found. It is an override to determine the default selected value. http://stackoverflow.com/a/16799915/1477388 – user1477388 May 28 '13 at 19:29
1

In my opinion one item of the ViewBag.ForeignLanguages should have Selected property set to true. DropDownListFor method select item based on ModelState. Here you have source code of DropDownListFor method an there is something like:

object defaultValue = (allowMultiple) ? htmlHelper.GetModelStateValue(fullName, typeof(string[])) : htmlHelper.GetModelStateValue(fullName, typeof(string));

And if that value is null then selected value is retrieved from Selected property

Sławomir Rosiek
  • 4,038
  • 3
  • 25
  • 43
1

I know this is an old question, but just in case someone is facing the same problem than me. In my case was that I accidentally was using a normal variable instead of a property in the model, as soon as I set it as a property instead it started working.

Rolando Retana
  • 412
  • 5
  • 16
  • I knew better! But this is exactly what was happening. It's a one-way model (no traditional postback) that I happen to be modifying to have a select list. Thanks for the reminder! – Ryan Woodham Mar 22 '17 at 21:45
0

I added an extension method to enforce the value selection. It also preserves view state data on a page reload.

public static class SelectListExtensions
{
    public static SelectList SelectValue(this SelectList selectList, object value)
    {
        return new SelectList(selectList, "Value", "Text", value);
    }
}

Usage is:

selectList = selectList.SelectValue(someValue);
Savage
  • 2,296
  • 2
  • 30
  • 40
0

I'm sending IEnumerable in SList instead of ViewBag

@Html.DropDownListFor(model => Model.list[i].Id, new SelectList(Model.SList, "Value", "Text", Model.list[i].Id), htmlAttributes: new { @class = "form-control" })
dnxit
  • 7,118
  • 2
  • 30
  • 34