从MVC 5.1 EnumDropDownListFor中排除/删除值

Jak*_*ond 37 c# asp.net-mvc enums html-helper razor

我有一个用于用户管理页面的枚举列表.我正在使用MVC 5.1中的新HtmlHelper,它允许我为Enum值创建一个下拉列表.我现在需要从列表中删除Pending值,此值只能以编程方式设置,并且永远不应由用户设置.

枚举:

public enum UserStatus
{
    Pending = 0,
    Limited = 1,
    Active = 2
}
Run Code Online (Sandbox Code Playgroud)

视图:

@Html.EnumDropDownListFor(model => model.Status)
Run Code Online (Sandbox Code Playgroud)

无论如何,要么覆盖当前控件,要么编写一个允许我指定枚举的自定义HtmlHelper,或者从结果列表中排除枚举?或者你会建议我用jQuery做客户端的东西,一旦生成后从下拉列表中删除值?

谢谢!

dav*_*v_i 45

您可以构建一个下拉列表:

@{ // 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)
Run Code Online (Sandbox Code Playgroud)

  • 在后端做`ViewBag.SelectList = selectList;`并在前面做`@Html.DropDownListFor(m => m.Status,(IEnumerable <SelectListItem>)ViewBag.SelectList)`应该工作(从内存!) (4认同)

Ste*_*ven 28

修改自@ dav_i的答案.

这并不完美,但它正是我所使用的.以下是对...的扩展HtmlHelper.扩展方法将类似于EnumDropDownListForASP.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;
}
Run Code Online (Sandbox Code Playgroud)

例如:

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

这将创建一个没有Active选项的Enum下拉列表.


And*_*NET 6

您可以通过循环枚举中的值来自己创建下拉列表,并且只包括<option>它是否未挂起.

以下是它应该如何工作,但正如您所看到的,我不确定您将使用哪个选项标签的值或文本.

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


Kyl*_*nes 5

我正在寻找这个问题的答案,因为它与 .NET Core MVC 相关。给定以下代码,您可以限制不想在 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>
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助其他寻找此答案的人。

  • 有点旧,但对我来说 Value 是字符串类型,所以将 x.Value != 0 更改为 x.Value != "0" 很不错 (2认同)