TestzWCh
TestzWCh

Reputation: 163

A way to make DropDownListFor with DropDowns inside in MVC Razor

Let's say i have a class Person which has

public string Name {get;set;}

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

and i'm trying to bind List<Person> to DropDownListFor so it would look like that

Dropdown:
  - First person
      - First string of the listOfStrings of first person
      - Second string of the listOfStrings of first person
  - Second Person
      - First string of the listOfStrings of second person
      - Second string of the listOfStrings of second person
      - third string of the listOfStrings of second person

etc

Is there a way to make it like that? only the strings in list should be selectable and not name of the person. I'm fine with anything

Upvotes: 0

Views: 100

Answers (2)

Chris Pratt
Chris Pratt

Reputation: 239460

This is relatively straight-forward. The only tricky part is selecting all the string values into one big list, while still keyed to a particular person. Thankfully SelectMany takes a resultSelector param that lets you do exactly that. Then, you just select everything into a list of SelectListItems and specify the Group property for each. Razor will then happily take care of generating the appropriate optgroups in the HTML. One thing of note: I think the ability to specify groups didn't come about until MVC 5, though.

ViewBag.DropDownOptions = db.People
    .SelectMany(m => m.ListOfStrings, (m, str) => new { Name = m.Name, String = str })
    .Select(m => new SelectListItem
    {
        Value = m.String,
        Text = m.String,
        Group = new SelectListGroup { Name = m.Name }
    });

Then, in your view:

@Html.DropDownListFor(m => m.Foo, (IEnumerable<SelectListItem>)ViewBag.DropDownOptions)

Upvotes: 2

Sam W
Sam W

Reputation: 599

I don't know if there is a Razor way of doing this other than a model and a foreach loop, but the HTML you are looking for will be something like this

<select>
  <optgroup label="Person1">
    <option value="ListOfStrings1">ListOfStrings1</option>
    <option value="ListOfStrings2">ListOfStrings2</option>
  </optgroup>
  <optgroup label="Person2">
    <option value="ListOfStrings3">ListOfStrings3</option>
    <option value="ListOfStrings4">ListOfStrings4</option>
  </optgroup>
</select>

Edit: as of MVC 5.2 there actually is a way to do this. You can find detailed instructions on how to create this HTML with Razor a little more elegantly than with a foreach loop here.

Upvotes: 1

Related Questions