How to add a -Choose something- from a DropDownList created out of an enum
I followed this blog to be able to create DropDownLists from several enums that we need in our ViewModels.
So far my code is looking like this:
public static class HtmlDropDownExtensions
{
private static readonly SelectListItem [] SingleEmptyItem = new[]{new SelectListItem{Text = string.Empty, Value = string.Empty}};
public static MvcHtmlString EnumDropDownList<TEnum>(this HtmlHelper htmlHelper, string modelPropertyName, TEnum selectedValue)
{
Type baseEnumType = Enum.GetUnderlyingType(typeof(TEnum));
IEnumerable<TEnum> values = Enum.GetValues(typeof (TEnum)).Cast<TEnum>();
IEnumerable<SelectListItem> items = GetSelectListItems(values, selectedValue, baseEnumType);
return htmlHelper.DropDownList(modelPropertyName, items);
}
public static MvcHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression)
{
var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
Type enumType = GetNonNullableModelType(metadata);
Type baseEnumType = Enum.GetUnderlyingType(enumType);
IEnumerable<TEnum> values = Enum.GetValues(enumType).Cast<TEnum>();
IEnumerable<SelectListItem> items = GetSelectListItems(values, metadata.Model, baseEnumType);
if (metadata.IsNullableValueType)
items = SingleEmptyItem.Concat(items);
return htmlHelper.DropDownListFor(expression, items);
}
private static Type GetNonNullableModelType(ModelMetadata modelMetadata)
{
Type realModelType = modelMetadata.ModelType;
Type underlyingType = Nullable.GetUnderlyingType(realModelType);
if(underlyingType != null)
realModelType = underlyingType;
return realModelType;
}
private static IEnumerable<SelectListItem> GetSelectListItems<TEnum>(IEnumerable<TEnum> values, object selectedValue, Type underlyingType)
{
return from value in values
select new SelectListItem
{
Text = value.ToString(),
Value = Convert.ChangeType(value, underlyingType).ToString(),
Selected = (value.Equals(selectedValue))
};
}
}
Now what I need is to be able to have a first option that prompts the user to select an option, be blank or unselected or something since the fields are required and there cannot be any defaults.
Update: I was thinking that maybe the "EnumDropDownList" method could add the empty SelectListItem before creating the DropDownList and returning the string. I have not tried that yet but I'm thinking that there will be an error when the MVC enginge tries to bind that to the ViewModel since it will not be possible t开发者_如何学Pythono parse that value into the ViewModel's enum property.
Thanks for you help.
Actually you already have everything implemented:
if (metadata.IsNullableValueType)
items = SingleEmptyItem.Concat(items);
If the model's property is of type Nullable<YourEnum>
, this code will add default item at the beginning of the DropDownList.
However, if the property does not allow nulls, the default value will not be rendered. And this is the correct behavior - user should be required to enter something and should not see any default items.
If you want to change the text of the default value, go the SingleEmptyItem
definition:
private static readonly SelectListItem [] SingleEmptyItem = new[]{new SelectListItem{Text = "Your text here", Value = string.Empty}};
精彩评论