MVC - Set selected value of SelectList

C#asp.net Mvc

C# Problem Overview


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

C# Solutions


Solution 1 - C#

If you have your SelectList object, just iterate through the items in it and set the "Selected" property of the item you wish.

foreach (var item in selectList.Items)
{
  if (item.Value == selectedValue)
  {
    item.Selected = true;
    break;
  }
}

Or with Linq:

var selected = list.Where(x => x.Value == "selectedValue").First();
selected.Selected = true;

Solution 2 - C#

A bit late to the party here but here's how simple this is:

ViewBag.Countries = new SelectList(countries.GetCountries(), "id", "countryName", "82");

this uses my method getcountries to populate a model called countries, obviousley you would replace this with whatever your datasource is, a model etc, then sets the id as the value in the selectlist. then just add the last param, in this case "82" to select the default selected item.

[edit] Here's how to use this in Razor:

@Html.DropDownListFor(model => model.CountryId, (IEnumerable<SelectListItem>)ViewBag.Countries, new { @class = "form-control" })

Important: Also, 1 other thing to watch out for, Make sure the model field that you use to store the selected Id (in this case model.CountryId) from the dropdown list is nullable and is set to null on the first page load. This one gets me every time.

Hope this saves someone some time.

Solution 3 - C#

Simply use the third parameter for selected value in mvc4

@Html.DropDownList("CountryList", new SelectList(ViewBag.Countries, "Value", "Text","974"))

Here "974" is selected Value Specified

In my result selected country is now qatar.in C# as below`

    foreach (CountryModel item in CountryModel.GetCountryList())
        {
            if (item.CountryPhoneCode.Trim() != "974")
            {
                countries.Add(new SelectListItem { Text = item.CountryName + " +(" + item.CountryPhoneCode + ")", Value = item.CountryPhoneCode });

            }
            else {

                
                countries.Add(new SelectListItem { Text = item.CountryName + " +(" + item.CountryPhoneCode + ")", Value = item.CountryPhoneCode,Selected=true });

            }
        }

Solution 4 - C#

Why are you trying to set the value after you create the list? My guess is you are creating the list in your model instead of in your view. I recommend creating the underlying enumerable in your model and then using this to build the actual SelectList:

<%= Html.DropDownListFor(m => m.SomeValue, new SelectList(Model.ListOfValues, "Value", "Text", Model.SomeValue)) %>

That way your selected value is always set just as the view is rendered and not before. Also, you don't have to put any unnecessary UI classes (i.e. SelectList) in your model and it can remain unaware of the UI.

Solution 5 - C#

Further to @Womp answer, it's worth noting that the "Where" Can be dropped, and the predicate can be put into the "First" call directly, like this:

list.First(x => x.Value == "selectedValue").Selected = true;

Solution 6 - C#

Doug answered my question... But I'll explain what my problem was exactly, and how Doug helped me solve my problem which you could be encountering.

I call jquery $.post and am replacing my div with my partial view, like so.

function AddNewAddress (paramvalue) {
    $.post(url, { param: paramvalue}, function(d) {
        $('#myDiv').replaceWith(d);
    });
}

When doing so, for some reason when stepping into my model my selected value affiliated property was never set, only until I stepped into the view it came into scope.

So, What I had before

@Html.DropDownListUnobtrusiveFor(model => model.CustomerAddresses[i].YearsAtAddress, Model.CustomerAddresses[i].YearsAtAddressSelectList, new {onchange = "return Address.AddNewAddress(this,'" + @Url.Action("AddNewAddress", "Address") + "'," + i + ")"})

however even though Model.CustomerAddresses[i].YearsAtAddressSelectList, was set... it didn't set the selected value.

So after....

 @Html.DropDownListUnobtrusiveFor(model => model.CustomerAddresses[i].YearsAtAddress, new SelectList(Model.CustomerAddresses[i].YearsAtAddressSelectList, "Value", "Text", Model.CustomerAddresses[i].YearsAtAddress), new { onchange = "return Address.AddNewAddress(this,'" + @Url.Action("AddNewAddress", "Address") + "'," + i + ")" })
                                

and it worked!

I decided not to use DropDownListFor as it has problem when using unobtrusive validation, which is why i reference the following if your curious in a class classed

HtmlExtensions.cs




[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types")]

public static MvcHtmlString DropDownListUnobtrusiveFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<SelectListItem> selectList)
{
    return DropDownListUnobtrusiveFor(htmlHelper, expression, selectList, null /* optionLabel */, null /* htmlAttributes */);

}


[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types")]

public static MvcHtmlString DropDownListUnobtrusiveFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<SelectListItem> selectList, object htmlAttributes)
{
    return DropDownListUnobtrusiveFor(htmlHelper, expression, selectList, null /* optionLabel */, new RouteValueDictionary(htmlAttributes));

}


[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types")]

public static MvcHtmlString DropDownListUnobtrusiveFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<SelectListItem> selectList, IDictionary<string, object> htmlAttributes)
{
    return DropDownListUnobtrusiveFor(htmlHelper, expression, selectList, null /* optionLabel */, htmlAttributes);

}


[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types")]

public static MvcHtmlString DropDownListUnobtrusiveFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<SelectListItem> selectList, string optionLabel)
{
    return DropDownListUnobtrusiveFor(htmlHelper, expression, selectList, optionLabel, null /* htmlAttributes */);

}


[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types")]

public static MvcHtmlString DropDownListUnobtrusiveFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<SelectListItem> selectList, string optionLabel, object htmlAttributes)
{
    return DropDownListUnobtrusiveFor(htmlHelper, expression, selectList, optionLabel, new RouteValueDictionary(htmlAttributes));

}


[SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "Users cannot use anonymous methods with the LambdaExpression type")]

[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types")]

public static MvcHtmlString DropDownListUnobtrusiveFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<SelectListItem> selectList, string optionLabel, IDictionary<string, object> htmlAttributes)
{
    if (expression == null)
    {
        throw new ArgumentNullException("expression");
    }


    ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);



    IDictionary<string, object> validationAttributes = htmlHelper
        .GetUnobtrusiveValidationAttributes(ExpressionHelper.GetExpressionText(expression), metadata);



    if (htmlAttributes == null)
        htmlAttributes = validationAttributes;
    else
        htmlAttributes = htmlAttributes.Concat(validationAttributes).ToDictionary(k => k.Key, v => v.Value);



    return SelectExtensions.DropDownListFor(htmlHelper, expression, selectList, optionLabel, htmlAttributes);

}

Solution 7 - C#

You can use below method, which is quite simple.

new SelectList(items, "ID", "Name",items.Select(x=> x.Id).FirstOrDefault());

This will auto-select the first item in your list. You can modify the above query by adding a where clause.

Solution 8 - C#

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.

Solution 9 - C#

I needed a dropdown in a editable grid myself with preselected dropdown values. Afaik, the selectlist data is provided by the controller to the view, so it is created before the view consumes it. Once the view consumes the SelectList, I hand it over to a custom helper that uses the standard DropDownList helper. So, a fairly light solution imo. Guess it fits in the ASP.Net MVC spirit at the time of writing; when not happy roll your own...

public static string DropDownListEx(this HtmlHelper helper, string name, SelectList selectList, object selectedValue)
{
return helper.DropDownList(name, new SelectList(selectList.Items, selectList.DataValueField, selectList.DataTextField, selectedValue));
}

Solution 10 - C#

I usually use this method

        public static SelectList SetSelectedValue(SelectList list, string value)
    {
        if (value != null)
        {
            var selected = list.Where(x => x.Value == value).First();
            selected.Selected = true;
            return list;
        }
        return list;
    }

Solution 11 - C#

I wanted the dropdown to select the matching value of the id in the action method. The trick is to set the Selected property when creating the SelectListItem Collection. It would not work any other way, perhaps I missed something but in end, it is more elegant in my option.

You can write any method that returns a boolean to set the Selected value based on your requirements, in my case I used the existing Equal Method

public ActionResult History(long id)
        {
            var app = new AppLogic();
            var historyVM = new ActivityHistoryViewModel();

            historyVM.ProcessHistory = app.GetActivity(id);
            historyVM.Process = app.GetProcess(id);
            var processlist = app.GetProcessList();

            historyVM.ProcessList = from process in processlist
                                    select new SelectListItem
                                    {
                                        Text = process.ProcessName,
                                        Value = process.ID.ToString(),
                                        Selected = long.Equals(process.ID, id)                                    
                                        
                                    };

            var listitems = new List<SelectListItem>();
            
            return View(historyVM);
        }

Solution 12 - C#

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;

Solution 13 - C#

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))

Solution 14 - C#

In case someone is looking I reposted my answer from: https://stackoverflow.com/questions/10553593/selectlistitem-selected-true-not-working-in-view/57566161#57566161

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

Solution 15 - C#

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionkaivalyaView Question on Stackoverflow
Solution 1 - C#wompView Answer on Stackoverflow
Solution 2 - C#Alex StephensView Answer on Stackoverflow
Solution 3 - C#mzonerzView Answer on Stackoverflow
Solution 4 - C#Doug LampeView Answer on Stackoverflow
Solution 5 - C#Immortal BlueView Answer on Stackoverflow
Solution 6 - C#AdamView Answer on Stackoverflow
Solution 7 - C#mcaView Answer on Stackoverflow
Solution 8 - C#Alvaro Rodriguez ScelzaView Answer on Stackoverflow
Solution 9 - C#Erik LenaertsView Answer on Stackoverflow
Solution 10 - C#FranchescoView Answer on Stackoverflow
Solution 11 - C#Adrian HedleyView Answer on Stackoverflow
Solution 12 - C#dfortunView Answer on Stackoverflow
Solution 13 - C#Mohamed HarounView Answer on Stackoverflow
Solution 14 - C#KenView Answer on Stackoverflow
Solution 15 - C#Kris BundaView Answer on Stackoverflow