MVC - Set selected value of SelectList

Viewed 261791

How can I set the selectedvalue property of a SelectList after it was instantiated without a selectedvalue;

SelectList selectList = new SelectList(items, "ID", "Name");

I need to set the selected value after this stage

15 Answers

I ended up here because SelectListItem is no longer picking the selected value correctly. To fix it, I changed the usage of EditorFor for a "manual" approach:

        <select id="Role" class="form-control">
            @foreach (var role in ViewBag.Roles)
            {
                if (Model.Roles.First().RoleId == role.Value)
                {
                    <option value="@role.Value" selected>@role.Text</option>
                }
                else
                {
                    <option value="@role.Value">@role.Text</option>
                }
            }
        </select>

Hope it helps someone.

Use LINQ and add the condition on the "selected" as a question mark condition.

    var listSiteId = (from site in db.GetSiteId().ToList()
                                      select new SelectListItem
                                      {
                                          Value = site.SITEID,
                                          Text = site.NAME,
                                          Selected = (dimension.DISPLAYVALUE == site.SITEID) ? true : false,
                                      }).ToList();
                    ViewBag.SiteId = listSiteId;

The below code solves two problems: 1) dynamically set the selected value of the dropdownlist and 2) more importantly to create a dropdownlistfor for an indexed array in the model. the problem here is that everyone uses one instance of the selectlist which is the ViewBoag.List, while the array needs one Selectlist instance for each dropdownlistfor to be able to set the selected value.

create the ViewBag variable as List (not SelectList) int he controller

//controller code
ViewBag.Role = db.LUT_Role.ToList();

//in the view @Html.DropDownListFor(m => m.Contacts[i].Role, new SelectList(ViewBag.Role,"ID","Role",Model.Contacts[i].Role))

In case someone is looking I reposted my answer from: SelectListItem selected = true not working in view

After searching myself for answer to this problem - I had some hints along the way but this is the resulting solution for me. It is an extension Method. I am using MVC 5 C# 4.52 is the target. The code below sets the Selection to the First Item in the List because that is what I needed, you might desire simply to pass a string and skip enumerating - but I also wanted to make sure I had something returned to my SelectList from the DB)

Extension Method:

public static class SelectListextensions {

public static System.Web.Mvc.SelectList SetSelectedValue

(this System.Web.Mvc.SelectList list, string value) { if (value != null) { var selected = list.Where(x => x.Text == value).FirstOrDefault(); selected.Selected = true;
} return list; }
}

And for those who like the complete low down (like me) here is the usage. The object Category has a field defined as Name - this is the field that will show up as Text in the drop down. You can see that test for the Text property in the code above.

Example Code:

SelectList categorylist = new SelectList(dbContext.Categories, "Id", "Name");

SetSelectedItemValue(categorylist);

select list function:

private SelectList SetSelectedItemValue(SelectList source) { Category category = new Category();

SelectListItem firstItem = new SelectListItem();

int selectListCount = -1;

if (source != null && source.Items != null)
{
    System.Collections.IEnumerator cenum = source.Items.GetEnumerator();

    while (cenum.MoveNext())
    {
        if (selectListCount == -1)
        {
            selectListCount = 0;
        }

        selectListCount += 1;

        category = (Category)cenum.Current;

        source.SetSelectedValue(category.Name);

        break;
    }
    if (selectListCount > 0)
    {
        foreach (SelectListItem item in source.Items)
        {
            if (item.Value == cenum.Current.ToString())
            {
                item.Selected = true;

                break;
            }
        }
    }
}
return source;

}

You can make this a Generic All Inclusive function / Extension - but it is working as is for me

There's a lot of good answers here, but there's also a lot of different ways to do this. Here's mine.

I consider this all the "front end" DDL code (all in a CSHTML page in .NET MVC with Entity Framework--thus the "Id" db references, and Bootstrap 3 styling with its jQuery front-end validation). I also refer to "front end" as I'm not showing any model annotations or controllers / repository / services code.

Here's the db table this DDL gets its values from:

enter image description here

It does that annoying thing of having a default value in the db table ("Not Applicable" or Id #4), but I've had to deal with this in the real world, so hopefully this example helps. The reason I'm on this page was to address a situation like this, and once I remembered how to do it, I thought I'd post what I did here in case it helps anyone else, and because the other answers aren't exactly like this.

Okay, here's what to do on a "Create" form, where you're creating your initial object. That's why the default selection is for #4 in the db table.

"Create" Form DDL example

<div class="form-group">
    @Html.LabelFor(
      m => m.Survey.CountryId, 
      "North American Country you live in?", new 
@* .required is custom CSS class to add red asterisk after label *@
      { @class = "col-md-4 control-label required" }
    )
    <div class="col-md-8">
        @Html.DropDownListFor(
            m => m.Survey.CountryId,
            Model.Surveys.Select(i => new SelectListItem()
            {
                Value = i.Id.ToString(),
                Text = $"{i.Code} - {i.Description}",
/*  gave default selection of Id #4 in db table */
                Selected = i.Id == 4 ? true : false
            }), new
            {
                @class = "form-control",
                data_val = "true",
                data_val_required = "This is a required selection"
            })
        @Html.ValidationMessageFor(m => m.Survey.CountryId)
    </div>
</div>

"Edit" Form DDL example


<div class="col-md-8">
    @Html.DropDownListFor(
        m => m.Survey.CountryId,
        Model.Surveys.Select(i => new SelectListItem()
        {
            Value = i.Id.ToString(),
            Text = $"{i.Code} - {i.Description}",
/* for Edit form, find the actual selected value the survey taker made */
            Selected = i.Id == Model.Survey.CountryId ? true : false
        }), new
        {
            @class = "form-control",
            data_val = "true",
            data_val_required = "This is a required selection"
        })
    @Html.ValidationMessageFor(m => m.Survey.CountryId)
</div>

And you could always do a default selection like this:

    @Html.DropDownListFor(
        m => m.Survey.CountryId,
        Model.Surveys.Select(i => new SelectListItem()
        {
            Value = i.Id.ToString(),
            Text = $"{i.Code} - {i.Description}",
            Selected = i.Id == Model.Survey.CountryId ? true : false
/* Add a default DDL selection when you're not trying to get it from a db */
        }), "-- select a country --", new
        {
            @class = "form-control"
        })

It should look something like this:

This DDL is for "State" and not "Country" and it has a default "-- Select --" choice but is more like the "Edit Form" version as it was already selected and is now showing that choice retrieved from the db.

But other than that...

enter image description here

Related