2

When I run the code, I can only select one item at a time, that's weird because 'ListBoxFor()' is used to select multiple items, so what i want is:

Select multiple items

View (Index.cshtml):

<div>
    @Html.ListBoxFor(m => m.DropDownItems, new MultiSelectList(Repository.DDFetchItems(), "Value", "Text", Model.DropDownItems))
</div>

Model (ModelVariables.cs):

public class ModelVariables
{
    public List<SelectListItem> DropDownItems { get; set; } 
}

public static class Repository
{
    public static List<SelectListItem> DDFetchItems()
    {
        return new List<SelectListItem>()
        {
            new SelectListItem(){  Text = "Dogs", Value = "1", Selected = true},
            new SelectListItem(){  Text = "Cats", Value = "2"},
            new SelectListItem(){  Text = "Death", Value = "3"}
        };
    }
}

Controller (HomeController.cs):

[HttpGet]
public ActionResult Index()
{
    ModelVariables model = new ModelVariables()
    {
        DropDownItems = Repository.DDFetchItems()  
    };
    return View(model);
}

1 Answers1

3

You cannot bind a <select multiple> to a collection of complex objects (which is what List<SelectListItem> is). A <select multiple> posts back an array of simple values (in your case, if you select the 1st and 3rd options, it will submit [1, 3] (the values of the selected options).

Your model needs a IEnumerable<int> property to bind to.

public class ModelVariables
{
    public IEnumerable<int> SelectedItems { get; set; }
    public IEnumerable<SelectListItem> DropDownItems { get; set; }
}

and then in the GET method

public ActionResult Index()
{
    var ModelVariables= new ModelVariables()
    {
        DropDownItems = Repository.DDFetchItems(),
        SelectedItems = new List<int>(){ 1, 3 } // to preselect the 1st and 3rd options
    };
    return View(model);
}

and in the view

@Html.ListBoxFor(m => m.SelectedItems, Model.DropDownItems)

Side notes

  1. Remove Selected = true in the DDFetchItems() method - its ignored by the ListBoxFor() method because its the value of the property your binding to which determines what is selected
  2. There is not need to build a new identical SelectList from the first one inside the ListBoxFor() method (property DropDownItems is already IEumerable<SelectListItem>)
  • Very good, i got it to work, HOWEVER, i could not pre-select items because i cannot convert from 'int' to , SelectedItems = new List() { 1, 3 }, it wants <'SelectListItem'> instead of 'int', due to me changing public IEnumerable SelectedItems { get; set; } –  Jun 16 '16 at 04:44
  • You cant change it to `IEnumerable SelectedItems` - that will never work as I explained (you **cannot** bind a ` –  Jun 16 '16 at 04:47
  • Ok i reverted it, now i get an error on x.Selected in var selectedMDDItems = model.SelectedItems.Where(x => x.Selected).Select(x => x.Text).ToList(); 'int does not contain a definition for 'Selected' and no extension method 'Selected' accepting a first argument of type 'int' –  Jun 16 '16 at 04:52
  • No. Your not understanding. The ` –  Jun 16 '16 at 04:57
  • Oh dear. Your need to repopulate the `SelectList` is you return the view. Read through [this question/answer](http://stackoverflow.com/questions/34366305/the-viewdata-item-that-has-the-key-xxx-is-of-type-system-int32-but-must-be-o) to understand –  Jun 16 '16 at 04:58
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/114800/discussion-between-stephen-muecke-and-fluffywuffy). –  Jun 16 '16 at 04:59