Подтвердить что ты не робот

Исключить/удалить значение из MVC 5.1 EnumDropDownListFor

У меня есть список перечислений, которые я использую для страницы управления пользователями. Я использую новый HtmlHelper в MVC 5.1, который позволяет мне создать раскрывающийся список для значений Enum. Теперь мне нужно удалить значение Pending из списка, это значение будет только когда-либо задано программно и никогда не должно быть установлено пользователем.

Enum:

public enum UserStatus
{
    Pending = 0,
    Limited = 1,
    Active = 2
}

Вид:

@Html.EnumDropDownListFor(model => model.Status)

В любом случае, переопределение текущего элемента управления или запись пользовательского HtmlHelper, который позволит мне указать перечисление или перечисления для исключения из результирующего списка? Или вы предложите мне сделать что-то клиентское с jQuery, чтобы удалить значение из раскрывающегося списка после его создания?

Спасибо!

4b9b3361

Ответ 1

Вы можете создать раскрывающийся список:

@{ // 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)

Ответ 2

Изменено из ответа @dav_i.

Это не идеально, но это то, что я использую. Ниже приведено расширение HtmlHelper. Метод расширения будет выглядеть как EnumDropDownListFor из ASP.NET и использовать DisplayAttribute, если какое-либо значение применяется к значению Enum.

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

Например:

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

Это создаст раскрывающийся список Enum без опции Active.

Ответ 3

Вы можете создать раскрывающийся список перейдя через значения в перечислении и включите только <option>, если он не находится в ожидании.

Вот как это должно работать, но, как вы можете видеть, я не уверен, что вы будете использовать для значения или текста тега опции.

<select>
foreach (var status in Enum.GetValues(typeof(UserStatus)))
{
    if(status != UserStatus.Pending)
    {
        <option value="status.???">@status.???</option>
    }
}
</select>

Ответ 4

Ниже приведено расширение для HtmlHelper. Он очень похож на расширение EnumDropDownListFor из ASP.NET, но он сортирует SelectListItem с помощью отображаемого имени элемента. У этого есть наводящее на размышления имя: SortedEnumDropDownListFor для конфликтов с исходным расширением.

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

Если вы не хотите беспокоиться о невыделенной позиции intitia, просто создайте такую ​​перегрузку:

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

И тебе хорошо идти. Надеюсь, это поможет.

Ответ 5

Я искал ответ на этот вопрос, поскольку он относится к .NET Core MVC. Используя следующий код, вы можете ограничить перечисления, которые вы не хотите отображать в пользовательском интерфейсе:

<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>

Надеюсь, что это поможет всем, кто ищет этот ответ.