MVC 5 Dropdownlistfor multiselect value binding in edit view

Raj picture Raj · Jan 7, 2019 · Viewed 8k times · Source

I have a select2 multiselect dropdown in edit view. When i try to bind selected values to the dropdown, it fails to bind. Any help appreciated. Please find below code snippets from *.cshtml and *.cs file.

@Html.DropDownListFor(model => model.Items, new MultiSelectList(ViewBag.ItemsBag, "Value", "Text", Model.ItemsSelected.Select(x => x.Value)), new { @class = "form-control features-segments select2-multiselect-checkbox", multiple = "multiple" })

ViewBag.ItemsBag = db.Items.Select(v => new SelectListItem
            {
                Text = v.ItemName,
                Value = v.ItemId.ToString()
            });

ModelVM modelVM = new ModelVM()
            {
                ItemsSelected = SelectedItems.Items.Select(x => new SelectListItem() { Text = x.ItemName, Value = x.ItemId.ToString() })
            };

Items model has below items. The property ItemsSelected is not null and has 3 values in it and ViewBag.ItemsBag is also not null and has all the items from the database. Both of these property are of type SelectListItem with properties Text and Value.

public int FeatureId { get; set; }
public string FeatureName { get; set; }
public string ReferenceName { get; set; }
public FeatureSection SectionName { get; set; }//Enum
public FeatureType Type { get; set; }//Enum
public bool DefaultBoolValue { get; set; }
public string DefaultTextValue { get; set; }
public IEnumerable<SelectListItem> ItemsSelected { get; set; }
public virtual ICollection<Item> Items { get; set; } = new List<Item>();

Answer

Tetsuya Yamamoto picture Tetsuya Yamamoto · Jan 7, 2019

Since you have item values provided in ViewBag definition like this, which clearly indicates string values:

ViewBag.ItemsBag = db.Items.Select(v => new SelectListItem
{
    Text = v.ItemName,
    Value = v.ItemId.ToString() // implies all values are strings
});

Then the property to bound with DropDownListFor/ListBox must have List<string> or string[] type to be bound properly. Using ICollection<Item> will not bound because it is a complex object, while the helper requires value types (numeric types/string) to bound with.

Hence, you must create a property with type List<string> first:

public List<string> SelectedValues { get; set; }

And then use ListBoxFor helper with that property instead:

@Html.ListBoxFor(model => model.SelectedValues, new MultiSelectList(ViewBag.ItemsBag, "Value", "Text", Model.ItemsSelected.Select(x => x.Value)), new { @class = "form-control features-segments select2-multiselect-checkbox", multiple = "multiple" })

Note:

If ItemId property has int type (and all values are convertible to int), try with List<int>/int[] type instead of List<string>/string[]:

public List<int> SelectedValues { get; set; }