繁体   English   中英

MVC3 EnumDropdownList选择的值

[英]MVC3 EnumDropdownList selected value

有一些有用的扩展方法,可用于在下拉列表中显示枚举。 例如在这里这里

但是我遇到一个问题,就是如果枚举用Description属性修饰,这些帮助器将无法工作。 第一个示例与Description属性完美配合,但未设置所选值。 第二个示例设置选定的值,但不使用description属性。 因此,我需要将这两种方法结合到一个可以正确完成工作的助手中。 我需要进行很多更改才能使其正常运行,但到目前为止没有成功。 我尝试了几种创建选择列表的方法,但是以某种方式它忽略了Selected属性。 在我所有的测试中,Selected属性在一项上都设置为true,但是只忽略了此属性。 因此,任何想法都是最欢迎的!

这是我尝试过的最新代码:

public static IEnumerable<SelectListItem> ToSelectList(Type enumType, string selectedItem)
    {
        List<SelectListItem> items = new List<SelectListItem>();
        foreach (var item in Enum.GetValues(enumType))
        {
            FieldInfo fi = enumType.GetField(item.ToString());
            var attribute = fi.GetCustomAttributes(typeof(DescriptionAttribute), true).FirstOrDefault();
            var title = attribute == null ? item.ToString() : ((DescriptionAttribute)attribute).Description;
            var listItem = new SelectListItem
            {
                Value = ((int)item).ToString(),
                Text = title,
                Selected = selectedItem == item.ToString()
            };

            items.Add(listItem);
        }
        return items;

    }

public static HtmlString EnumDropDownList2For<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> modelExpression)
    {
        var typeOfProperty = modelExpression.ReturnType;
        if (!typeOfProperty.IsEnum)
            throw new ArgumentException(string.Format("Type {0} is not an enum", typeOfProperty));

        var value = htmlHelper.ViewData.Model == null
            ? default(TProperty)
            : modelExpression.Compile()(htmlHelper.ViewData.Model);

        return htmlHelper.DropDownListFor(modelExpression, ToSelectList(modelExpression.ReturnType, value.ToString()));
    }

我对枚举有相同的问题,实际上已设置了自定义值

public enum Occupation
{
    [Description("Lorry driver")] LorryDriver = 10,
    [Description("The big boss")] Director = 11,
    [Description("Assistant manager")] AssistantManager = 12
}

我发现的是,当我使用DropDownListFor()时,它不使用SelectListItem集合中的选定项来设置选定的选项。 相反,它选择一个值等于我尝试绑定到的属性的选项(m => m.Occupation),为此,它使用枚举的.ToString()而不是枚举的实际整数值。 所以我最终要像这样设置SelectListItem的Value:

var listItem = new SelectListItem
{
    Value = item.ToString(), // use item.ToString() instead
    Text = title,
    Selected = selectedItem == item.ToString() // <- no need for this
};

辅助方法:

public static class SelectListItemsForHelper
{
    public static IEnumerable<SelectListItem> SelectListItemsFor<T>(T selected) where T : struct
    {
        Type t = typeof(T);
        if (t.IsEnum)
        {
            return Enum.GetValues(t).Cast<Enum>().Select(e => new SelectListItem { Value = e.ToString(), Text = e.GetDescription() });
        }
        return null;
    }

    public static string GetDescription<TEnum>(this TEnum value)
    {
        FieldInfo fi = value.GetType().GetField(value.ToString());

        if (fi != null)
        {
            var attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);

            if (attributes.Length > 0)
                return attributes[0].Description;
        }

        return value.ToString();
    }
}

在视图中:

@Html.DropDownListFor(m => m.Occupation, SelectListItemsForHelper.SelectListItemsFor(Model.Occupation), String.Empty)

总结有效的解决方案(至少对我而言):

我使用以下一组辅助方法

public static IEnumerable<SelectListItem> ToSelectList(Type enumType, string selectedItem)
    {
        List<SelectListItem> items = new List<SelectListItem>();
        foreach (var item in Enum.GetValues(enumType))
        {
            var title = item.GetDescription();
            var listItem = new SelectListItem
            {
                Value = item.ToString(),
                Text = title,
                Selected = selectedItem == item.ToString()
            };

            items.Add(listItem);
        }
        return items;

    }

public static MvcHtmlString EnumDropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression) where TModel : class
    {
        string inputName = GetInputName(expression);
        var value = htmlHelper.ViewData.Model == null
            ? default(TProperty)
            : expression.Compile()(htmlHelper.ViewData.Model);

        return htmlHelper.DropDownList(inputName, ToSelectList(typeof(TProperty), value.ToString()));
    }

public static string GetInputName<TModel, TProperty>(Expression<Func<TModel, TProperty>> expression)
    {
        if (expression.Body.NodeType == ExpressionType.Call)
        {
            MethodCallExpression methodCallExpression = (MethodCallExpression)expression.Body;
            string name = GetInputName(methodCallExpression);
            return name.Substring(expression.Parameters[0].Name.Length + 1);

        }
        return expression.Body.ToString().Substring(expression.Parameters[0].Name.Length + 1);
    }

    private static string GetInputName(MethodCallExpression expression)
    {
        MethodCallExpression methodCallExpression = expression.Object as MethodCallExpression;
        if (methodCallExpression != null)
        {
            return GetInputName(methodCallExpression);
        }
        return expression.Object.ToString();
    }

用法:

@Html.EnumDropDownListFor(m => m.MyEnumType)

这适用于具有或不具有描述属性的枚举,并设置正确的所选值。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM