从MVC 5.1 EnumDropDownListFor中排除/删除值
我有一个用于用户管理页面的枚举列表。 我正在使用MVC 5.1中的新HtmlHelper,它允许我为Enum值创建一个下拉列表。 我现在需要从列表中删除Pending值,此值只能以编程方式设置,并且永远不应由用户设置。
枚举:
public enum UserStatus { Pending = 0, Limited = 1, Active = 2 }
视图:
@Html.EnumDropDownListFor(model => model.Status)
无论如何,要么覆盖当前控件,要么编写一个允许我指定枚举的自定义HtmlHelper,或者从结果列表中排除枚举? 或者你会建议我用jQuery做客户端的东西,一旦生成后从下拉列表中删除值?
谢谢!
您可以构建一个下拉列表:
@{ // you can put the following in a back-end method and pass through ViewBag var selectList = Enum.GetValues(typeof(UserStatus)) .Cast() .Where(e => e != UserStatus.Pending) .Select(e => new SelectListItem { Value = ((int)e).ToString(), Text = e.ToString() }); } @Html.DropDownListFor(m => m.Status, selectList)
修改自@ dav_i的答案。
这并不完美,但它正是我所使用的。 以下是HtmlHelper
的扩展。 扩展方法看起来像ASP.NET中的EnumDropDownListFor
,如果有任何应用于Enum值,则使用DisplayAttribute
。
/// /// Returns an HTML select element for each value in the enumeration that is /// represented by the specified expression and predicate. /// /// The type of the model. /// The type of the value. /// The HTML helper instance that this method extends. /// An expression that identifies the object that contains the properties to display. /// The text for a default empty item. This parameter can be null. /// A to filter the items in the enums. /// An object that contains the HTML attributes to set for the element. /// An HTML select element for each value in the enumeration that is represented by the expression and the predicate. /// If expression is null. /// If TEnum is not Enum Type. public static MvcHtmlString EnumDropDownListFor(this HtmlHelper htmlHelper, Expression> expression, Func 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 selectList = Enum.GetValues(typeof(TEnum)) .Cast() .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); } /// /// Gets the name in of the Enum. /// /// A that the method is extended to. /// A name string in the of the Enum. 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" });
这将创建一个没有Active选项的Enum下拉列表。
您可以通过循环枚举中的值来自己创建下拉列表,如果它不是Pending,则只包括 。
以下是它应该如何工作,但正如您所看到的,我不确定您将使用哪个选项标记的值或文本。
下面是HtmlHelper的扩展。 它与ASP.NET中的EnumDropDownListFor扩展非常相似,但它按项目显示名称对SelectListItem进行排序。 它有一个暗示名称:SortedEnumDropDownListFor,用于不与原始扩展名冲突。
/// /// /// /// The type of the model. /// The type of the value. /// The HTML helper instance that this method extends. /// An expression that identifies the object that contains the properties to display /// The unselected item initial value /// /// public static MvcHtmlString SortedEnumDropDownListFor(this HtmlHelper htmlHelper, Expression> expression, string initalValue, object htmlAttributes = null) { ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData); Type enumType = GetNonNullableModelType(metadata); Type baseEnumType = Enum.GetUnderlyingType(enumType); List items = new List (); 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()) { text = displayAttribute.GetName(); } items.Add(new SelectListItem { Text = text, Value = value, Selected = selected }); } items = new List(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(this HtmlHelper htmlHelper, Expression> expression, object htmlAttributes = null) { MvcHtmlString helper = SortedEnumDropDownListFor(htmlHelper, expression, string.Empty, htmlAttributes); return helper; }
你很高兴。 我希望它有所帮助。