Building <select> tags generates a few questions and is something I've written about before (see Dropdown Lists and ASP.NET MVC). Here's a quick example to examine the scenario from different perspectives with the DropDownListFor HTML helper.
Let's say you have a class to represent different flavors of ice cream.
public class IceCreamFlavor { public int Id { get; set; } public string Name { get; set; } }
With DropDownListFor, you typically want a view model that will contain at least 2 properties:
- one property to hold a collection of SelectListItems to build the drop down
- one property to hold the value selected by a user
public class ViewModel { private readonly List<IceCreamFlavor> _flavors; [Display(Name = "Favorite Flavor")] public int SelectedFlavorId { get; set; } public IEnumerable<SelectListItem> FlavorItems { get { return new SelectList(_flavors, "Id", "Name");} } }
Assuming the _flavors field is populated with real ice cream flavors from a database or elsewhere, then the following Razor code:
@Html.LabelFor(m=>m.SelectedFlavorId) @Html.DropDownListFor(m => m.SelectedFlavorId, Model.FlavorItems) @Html.ValidationMessageFor(m=>m.SelectedFlavorId) <input type="submit" value="Submit" />
.. will give you this in a browser:
The constructor for a SelectList wants you to identify the data field and text field using strings ("Id" and "Name"). If you want strong typing, use LINQ to project ice cream flavors into SelectListItems.
public IEnumerable<SelectListItem> FlavorItems { get { var allFlavors = _flavors.Select(f => new SelectListItem { Value = f.Id.ToString(), Text = f.Name }); return allFlavors; } }
Perhaps you want to prepend a "Select Something Here" item into the option list for the drop down.
public IEnumerable<SelectListItem> FlavorItems { get { var allFlavors = _flavors.Select(f => new SelectListItem { Value = f.Id.ToString(), Text = f.Name }); return DefaultFlavorItem.Concat(allFlavors); } } public IEnumerable<SelectListItem> DefaultFlavorItem { get { return Enumerable.Repeat(new SelectListItem { Value = "-1", Text = "Select a flavor" }, count: 1); } }
Something you might notice if validation fails is that the drop down list seems to remember the last value selected without you doing any extra work.
In other words, if the user selects "Chocolate" and clicks Submit to post the form to the server, your controller might detect a validation error and re-render the form with validation messages. The drop down list will also re-build the <select> from scratch, but somehow "Choclate" is selected instead of "Select A Flavor". You'll see this behavior because DropDownListFor will peek in ModelState to see the last value for SelectedFlavorId, and build the drop down list with the last selected flavor marked as selected. It's the same magic Web Form programmers see with ViewState.
Hope that helps!