从 MVC 5.1 EnumDropDownListFor 中排除/删除值
本文关键字:排除 删除 EnumDropDownListFor MVC | 更新日期: 2023-09-27 18:31:51
我有一个用于用户管理页面的枚举列表。我正在使用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<UserStatus>()
.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
。
/// <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");
}
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" })
这将创建一个不带"活动"选项的枚举下拉列表。
循环访问枚举中的值来自己创建下拉列表,并且仅在<option>
未挂起时才包含下拉列表。
这是它应该如何工作,但如您所见,我不确定您将使用什么作为选项标签的值或文本。
<select>
foreach (var status in Enum.GetValues(typeof(UserStatus)))
{
if(status != UserStatus.Pending)
{
<option value="status.???">@status.???</option>
}
}
</select>
我一直在寻找这个问题的答案,因为它与.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>
希望这有助于其他寻找此答案的人。
下面是 HtmlHelper 的扩展。它与 ASP.NET 中的 EnumDropDownListFor 扩展非常相似,但它按项目显示名称对 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;
}
如果您不想打扰未选择的项目初始化,只需构建如下所示的重载:
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;
}
你很好去。我希望它有所帮助。