Bind DropDownListFor with List on ViewModel

2019-07-16 21:01发布

问题:

I'm trying to do this:

This is my ViewModel and Model:

public class OpeningYearViewModel
{
    public int OpeningYearId { get; set; }
    public string Description { get; set; }
    public List<Grade> GradesList { get; set; }
}

public class Grade
{
    public int GradeId { get; set; }
    public string Name { get; set; }
    public int CurrencyId { get; set; }
    public int Cost { get; set; }
}

This is my Controller. I build a SelecList here and pass it to the view through the ViewBag

OpeningYearViewModel viewmodel = new OpeningYearViewModel {

    OpeningYearId = 1,
    Description = "2015 - II",
    GradesList = new List<Grade>
    {
        new Grade { GradeId = 1, Name = "Grade 1", CurrencyId = 1, Cost = 100 },
        new Grade { GradeId = 2, Name = "Grade 2", CurrencyId = 2, Cost = 200 },
        new Grade { GradeId = 3, Name = "Grade 3", CurrencyId = 2, Cost = 150 }
    }
};

SelectList list = new SelectList(
                    new List<SelectListItem> 
                    {
                        new SelectListItem { Text = "S/.", Value = "1"},
                        new SelectListItem { Text = "$", Value = "2"},
                     }, "Value" , "Text");

ViewBag.currencyList = list;

return View(viewmodel);

And in my View I need a DropDownListFor for every item on GradesList so I do this:

@model Test.Models.OpeningYearViewModel

@for(int i = 0; i < Model.GradesList.Count; i++)
{
  @Html.DropDownListFor(x => x.GradesList[i].CurrencyId, new SelectList(ViewBag.currencyList, "Value", "Text"))
  @Model.GradesList[i].CurrencyId //This is just to know the CurrencyId on every item.
}

I'm getting every select correctly rendered, but I can't get the correct option selected on the page load: render of view

It is possible to do what I'm trying to do and I'm doing something wrong, or DropDownListFor works in a different way?

Thanks!

回答1:

I can't understand why this is happening but you can workaround it by setting explicitly the selected value. This can be done by passing Model.GradesList[i].CurrencyId as fourth parameter to the SelectList's constructor:

@for(int i = 0; i < Model.GradesList.Count; i++)
{
    @Html.DropDownListFor(x => x.GradesList[i].CurrencyId, 
        new SelectList(ViewBag.currencyList, "Value", "Text", Model.GradesList[i].CurrencyId))
}


回答2:

Since, the DropDownListFor is used in loop to generate indexed inputs; so generate input controls will be generated with name as "GradeList[0].CurrencyId", "GradeList[1].CurrencyId"......Due to this framework will not bind the selected value in Select List as it is unable to get the value in reflection for selection. That's why you have to use the following SelectList constructor to set the selected value.

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

However, if your DropDownListFor is bind to a simple expression like

@Html.DropDownListFor(model => model.CurrencyId, new SelectList(ViewBag.Items, "Value", "Text"))

then selection will work automatically.