如何从枚举创建的DropDownList中添加-hoose something-

时间:2011-10-03 23:33:11

标签: c# asp.net-mvc-2

我跟着this blog能够从ViewModel中需要的几个枚举中创建DropDownLists。

到目前为止,我的代码看起来像这样:

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))
           };
    }
}

现在我需要的是能够有一个第一个选项,提示用户选择一个选项,空白或未选择或某些东西,因为这些字段是必需的,并且没有任何默认值。

更新 我在想,也许“EnumDropDownList”方法可能会在创建DropDownList并返回字符串之前添加空的SelectListItem。我还没有尝试过,但我认为当MVC引入尝试将其绑定到ViewModel时会出现错误,因为无法将该值解析为ViewModel的枚举属性。

谢谢你的帮助。

1 个答案:

答案 0 :(得分:0)

实际上你已经实现了一切:

if (metadata.IsNullableValueType)
    items = SingleEmptyItem.Concat(items);

如果模型的属性类型为Nullable<YourEnum>,则此代码将在DropDownList的开头添加默认项。

但是,如果属性不允许空值,则不会呈现默认值。这是正确的行为 - 用户应该被要求输入内容而不应该看到任何默认项目。

如果要更改默认值的文本,请转到SingleEmptyItem定义:

private static readonly SelectListItem [] SingleEmptyItem = new[]{new SelectListItem{Text = "Your text here", Value = string.Empty}};