Exclude/Remove Value from MVC 5.1 EnumDropDownListFor

前端 未结 5 1657
隐瞒了意图╮
隐瞒了意图╮ 2020-12-13 06:01

I have a list of enums that I am using for a user management page. I\'m using the new HtmlHelper in MVC 5.1 that allows me to create a dropdown list for Enum values. I now h

相关标签:
5条回答
  • 2020-12-13 06:43

    You could construct a drop down list:

    @{ // you can put the following in a back-end method and pass through ViewBag
       var selectList = Enum.GetValues(typeof(UserStatus))
                            .Cast<UserStatus>()
                            .Where(e => e != UserStatus.Pending)
                            .Select(e => new SelectListItem 
                                { 
                                    Value = ((int)e).ToString(),
                                    Text = e.ToString()
                                });
    }
    @Html.DropDownListFor(m => m.Status, selectList)
    
    0 讨论(0)
  • 2020-12-13 06:45

    You can create the dropdown yourself by looping through the values in the enum and only include the <option> if it is not Pending.

    Here is how it should work, but as you can see, I'm not sure what you would use for the value or text of the option tag.

    <select>
    foreach (var status in Enum.GetValues(typeof(UserStatus)))
    {
        if(status != UserStatus.Pending)
        {
            <option value="status.???">@status.???</option>
        }
    }
    </select>
    
    0 讨论(0)
  • 2020-12-13 06:46

    Modified from @dav_i's answer.

    This is not perfect, but it is what I am using. Below is an extension to HtmlHelper. The extension method will look like EnumDropDownListFor from ASP.NET, and use DisplayAttribute if there is any applied to the Enum value.

    /// <summary>
    /// Returns an HTML select element for each value in the enumeration that is
    /// represented by the specified expression and predicate.
    /// </summary>
    /// <typeparam name="TModel">The type of the model.</typeparam>
    /// <typeparam name="TEnum">The type of the value.</typeparam>
    /// <param name="htmlHelper">The HTML helper instance that this method extends.</param>
    /// <param name="expression">An expression that identifies the object that contains the properties to display.</param>
    /// <param name="optionLabel">The text for a default empty item. This parameter can be null.</param>
    /// <param name="predicate">A <see cref="Func{TEnum, bool}"/> to filter the items in the enums.</param>
    /// <param name="htmlAttributes">An object that contains the HTML attributes to set for the element.</param>
    /// <returns>An HTML select element for each value in the enumeration that is represented by the expression and the predicate.</returns>
    /// <exception cref="ArgumentNullException">If expression is null.</exception>
    /// <exception cref="ArgumentException">If TEnum is not Enum Type.</exception>
    public static MvcHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression, Func<TEnum, bool> predicate, string optionLabel, object htmlAttributes) where TEnum : struct, IConvertible
    {
        if (expression == null)
        {
            throw new ArgumentNullException("expression");
        }
    
        if (!typeof(TEnum).IsEnum)
        {
            throw new ArgumentException("TEnum");
        }
    
        ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
        IList<SelectListItem> selectList = Enum.GetValues(typeof(TEnum))
                .Cast<TEnum>()
                .Where(e => predicate(e))
                .Select(e => new SelectListItem
                    {
                        Value = Convert.ToUInt64(e).ToString(),
                        Text = ((Enum)(object)e).GetDisplayName(),
                    }).ToList();
        if (!string.IsNullOrEmpty(optionLabel)) {
            selectList.Insert(0, new SelectListItem {
                Text = optionLabel,
            });
        }
    
        return htmlHelper.DropDownListFor(expression, selectList, htmlAttributes);
    }
    
    /// <summary>
    /// Gets the name in <see cref="DisplayAttribute"/> of the Enum.
    /// </summary>
    /// <param name="enumeration">A <see cref="Enum"/> that the method is extended to.</param>
    /// <returns>A name string in the <see cref="DisplayAttribute"/> of the Enum.</returns>
    public static string GetDisplayName(this Enum enumeration)
    {
        Type enumType = enumeration.GetType();
        string enumName = Enum.GetName(enumType, enumeration);
        string displayName = enumName;
        try
        {
            MemberInfo member = enumType.GetMember(enumName)[0];
    
            object[] attributes = member.GetCustomAttributes(typeof(DisplayAttribute), false);
            DisplayAttribute attribute = (DisplayAttribute)attributes[0];
            displayName = attribute.Name;
    
            if (attribute.ResourceType != null)
        {
                displayName = attribute.GetName();
            }
        }
        catch { }
        return displayName;
    }
    

    For example:

    @Html.EnumDropDownListFor(
        model => model.UserStatus,
        (userStatus) => { return userStatus != UserStatus.Active; },
        null,
        htmlAttributes: new { @class = "form-control" });
    

    This will create a Enum dropdown list without the the option of Active.

    0 讨论(0)
  • 2020-12-13 06:49

    Below is an extension to the HtmlHelper. It is very similar to the EnumDropDownListFor extension from ASP.NET, but it sorts the SelectListItem by the item display name. It has a suggestive name: SortedEnumDropDownListFor for not conflicts with the original extension.

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TModel">The type of the model.</typeparam>
        /// <typeparam name="TEnum">The type of the value.</typeparam>
        /// <param name="htmlHelper">The HTML helper instance that this method extends.</param>
        /// <param name="expression">An expression that identifies the object that contains the properties to display</param>
        /// <param name="initalValue">The unselected item initial value</param>
        /// <param name="htmlAttributes"></param>
        /// <returns></returns>
        public static MvcHtmlString SortedEnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression, string initalValue, object htmlAttributes = null)
        {
    
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
    
            Type enumType = GetNonNullableModelType(metadata);
            Type baseEnumType = Enum.GetUnderlyingType(enumType);
            List<SelectListItem> items = new List<SelectListItem>();
    
            foreach (FieldInfo field in enumType.GetFields(BindingFlags.Static | BindingFlags.GetField | BindingFlags.Public))
            {
                string text = field.Name;
                string value = Convert.ChangeType(field.GetValue(null), baseEnumType).ToString();
                bool selected = field.GetValue(null).Equals(metadata.Model);
    
                foreach (DisplayAttribute displayAttribute in field.GetCustomAttributes(true).OfType<DisplayAttribute>())
                {
                    text = displayAttribute.GetName();
                }
    
                items.Add(new SelectListItem
                {
                    Text = text,
                    Value = value,
                    Selected = selected
                });
            }
    
            items = new List<SelectListItem>(items.OrderBy(s => s.Text));
            items.Insert(0, new SelectListItem { Text = initalValue, Value = "" });
    
            return htmlHelper.DropDownListFor(expression, items, htmlAttributes);
    
        }        
    
        private static Type GetNonNullableModelType(ModelMetadata modelMetadata)
        {
            Type realModelType = modelMetadata.ModelType;
            Type underlyingType = Nullable.GetUnderlyingType(realModelType);
    
            if (underlyingType != null)
            {
                realModelType = underlyingType;
            }
    
            return realModelType;
        }
    

    If you don't want to bother with the unselected item intitia, just build a overload like this:

    public static MvcHtmlString SortedEnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression, object htmlAttributes = null)
            {
                MvcHtmlString helper = SortedEnumDropDownListFor(htmlHelper, expression, string.Empty, htmlAttributes);
                return helper;
            }
    

    And you are good to go. I hope it helps.

    0 讨论(0)
  • 2020-12-13 06:54

    I was looking for the answer to this question as it relates to .NET Core MVC. Given the following code, you can limit the enums you do not want to display within the UI:

    <select asp-for="UserStatus" asp-items="@(Html.GetEnumSelectList<UserStatus>().Where(x => x.Value != 0))" class="form-control">
        <option selected="selected" value="">Please select</option>
    </select>
    

    Hope this helps anyone else looking for this answer.

    0 讨论(0)
提交回复
热议问题