@{ List<selectlistitem> items = new List<selectlistitem> { new SelectListItem {Text = "Red", Value = "Red", Selected = Model.FavoriteColor == "Red"}, new SelectListItem {Text = "Green", Value = "Green", Selected = Model.FavoriteColor == "Green"}, new SelectListItem {Text = "Blue", Value = "Blue", Selected = Model.FavoriteColor == "Blue"} }; } @Html.DropDownListFor(model => model.FavoriteColor, items)
In this case, FavoriteColor is a string property that has some options on a list for convenience. But what if it was an Enum?
public enum Colors { Red, Green, Blue }
We can use some fancy maneuvering and LINQ to create a dropdown list in one command:
@Html.DropDownListFor(model => model.FavoriteColor, Enum.GetValues(typeof(Colors)).Cast<colors>().Select(color => new SelectListItem { Text = Colors.ToString(), Value = Colors.ToString(), Selected = model.FavoriteColor == color }))
This LINQ query uses the static method GetValues to get a list of all entries in an enum. They get casted to their appropriate type and then a new SelectListItem is selected out of them. This works great, but it's a bit too much work. Let's try an HtmlHelper extension method:
public static class HtmlHelperExtensions { public static MvcHtmlString DropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression) { } }
By creating a new static class and adding it to the same namespace as the view (or adding a "using" statement to the top of the view), we will now see a new overload for the DropDownListFor method which takes only one parameter, the property expression.
@Html.DropDownListFor(model => model.FavoriteColor)
In populating the method, it has to do 5 things:
- It must establish the name of the property
- It must establish the type of the property and ensure it is an enum
- It must get a list of all possible options for the enum
- It must create a list of SelectListItems
- Finally, it must return a dropdown list
public static MvcHtmlString DropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression) { var propertyName = ExpressionHelper.GetExpressionText(expression); var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData); var propertyInfo = metadata.ContainerType.GetProperty(propertyName); if (!propertyInfo.PropertyType.IsEnum) throw new InvalidParameterException("Must use with a property of an Enum type."); var options = Enum.GetValues(propertyInfo.PropertyType).Cast<object>().Select(o => o.ToString()).ToList(); var descriptions = propertyInfo.PropertyType.GetEnumDescriptions(); var selectedOption = metadata.Model.ToString(); var selectList = options.Select(option => new SelectListItem {Text = descriptions[option], Value = option, Selected = option == selectedOption}); return htmlHelper.DropDownListFor(expression, selectList); }For more information, check out our website.
This blog entry provides an excellent and clear explanation of how to create an HTML Extension to the DropDownListFor helper. C# should provide this functionality to convert an enum to a DropDownListFor. So this is a good solution to add the functionality to your project.
ReplyDelete