SelectExtensions MVC扩展
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Web;
using System.Web.Mvc;
namespace System.Web.Mvc.Html
{
public static class SelectExtensions
{
public static MvcHtmlString EnumDropDownGroupListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes)
{
return EnumDropDownGroupListFor<TModel, TProperty>(htmlHelper, expression, null, htmlAttributes);
}
public static MvcHtmlString EnumDropDownGroupListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, string optionLabel, object htmlAttributes)
{
ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
Enum currentValue = metadata.Model as Enum;
IList<SelectListItem> selectList = GetSelectList(metadata.ModelType, currentValue);
TagBuilder tagBuilder = GenerateTagBuilder(htmlHelper, expression, new SelectListItem[1]
{
new SelectListItem
{
Text=optionLabel,
}
}, htmlAttributes, metadata, selectList);
return new MvcHtmlString(tagBuilder.ToString(TagRenderMode.Normal));
}
public static MvcHtmlString FlagEnumDropDownListFor<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, int>> expression, Type enumType, object htmlAttributes)
{
return FlagEnumDropDownListFor<TModel>(htmlHelper, expression, enumType, "", htmlAttributes);
}
public static MvcHtmlString FlagEnumDropDownListFor<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, int>> expression, Type enumType, SelectListItem[] beforeInit, object htmlAttributes)
{
ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
int currentValue = Convert.ToInt32(metadata.Model);
Enum[] values = GetEnumValues(currentValue, enumType);
IList<SelectListItem> selectList = GetSelectList(enumType, values);
TagBuilder tagBuilder = GenerateTagBuilder(htmlHelper, expression, beforeInit, htmlAttributes, metadata, selectList);
return new MvcHtmlString(tagBuilder.ToString(TagRenderMode.Normal));
}
public static MvcHtmlString FlagEnumDropDownListFor<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, int>> expression, Type enumType, string optionLabel, object htmlAttributes)
{
return FlagEnumDropDownListFor(htmlHelper, expression, enumType, new SelectListItem[1]
{
new SelectListItem
{
Text=optionLabel,
}
}, htmlAttributes);
}
private static TagBuilder GenerateTagBuilder<TModel, TProperty>(HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, SelectListItem[] beforeInit, object htmlAttributes, ModelMetadata metadata, IList<SelectListItem> selectList)
{
StringBuilder listItemBuilder = BuildItems(beforeInit, selectList);
TagBuilder tagBuilder = new TagBuilder("select")
{
InnerHtml = listItemBuilder.ToString()
};
string expressionName = ExpressionHelper.GetExpressionText(expression);
string fullName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(expressionName);
tagBuilder.MergeAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
tagBuilder.MergeAttribute("name", fullName, true);
tagBuilder.GenerateId(fullName);
ModelState modelState;
if (htmlHelper.ViewData.ModelState.TryGetValue(fullName, out modelState))
{
if (modelState.Errors.Count > 0)
{
tagBuilder.AddCssClass(HtmlHelper.ValidationInputCssClassName);
}
}
tagBuilder.MergeAttributes(htmlHelper.GetUnobtrusiveValidationAttributes(fullName, metadata));
return tagBuilder;
}
private static Enum[] GetEnumValues(int value, Type enumType)
{
var enums = Enum.GetValues(enumType).Cast<Enum>().ToArray();
List<Enum> result = new List<Enum>();
FlagsAttribute attribute = Attribute.GetCustomAttribute(enumType, typeof(FlagsAttribute)) as FlagsAttribute;
bool isFlagsEnum = attribute != null;
Array.ForEach(enums, p =>
{
var flagValue = isFlagsEnum ? Convert.ToInt32(p) : (1 << Convert.ToInt32(p));
if ((flagValue & value) > 0)
{
result.Add(p);
}
});
return result.ToArray();
}
private static IList<SelectListItem> GetSelectList(Type type, Enum selectedValue = null)
{
return GetSelectList(type, selectedValue == null ? null : new Enum[1] { selectedValue });
}
private static IList<SelectListItem> GetSelectList(Type type, Enum[] selectedValue = null)
{
IList<SelectListItem> selectList = GetSelectItems(type);
string[] valueStrings = (selectedValue == null) ? null : selectedValue.Select(m => m.ToString("d")).ToArray();
foreach (SelectListItem item in selectList)
{
item.Selected = valueStrings != null && (valueStrings.Contains(item.Value));
}
return selectList;
}
/// <summary>
/// 将枚举中的值组合为List
/// </summary>
/// <param name="enumType"></param>
/// <returns></returns>
private static IList<SelectListItem> GetSelectItems(Type enumType)
{
IList<SelectListItem> selectList = new List<SelectListItem>();
Type checkedType = Nullable.GetUnderlyingType(enumType) ?? enumType;
if (checkedType != enumType)
{
selectList.Add(new SelectListItem { Text = String.Empty, Value = String.Empty });
}
foreach (object e in Enum.GetValues(enumType))
{
string groupName = HtmlExtensions.EnumDisplayGroupFor(e);
selectList.Add(new SelectListItem()
{
Group = groupName == null ? null : new SelectListGroup { Name = HtmlExtensions.EnumDisplayGroupFor(e) },
Text = HtmlExtensions.EnumDisplayNameFor(e),//GetDisplayName(enumType, e.ToString(), AttributeTargets.Field),
Value = ((int)e).ToString()
});
}
return selectList;
}
private static StringBuilder BuildItems(SelectListItem[] selectItems, IEnumerable<SelectListItem> selectList)
{
StringBuilder listItemBuilder = new StringBuilder();
if (selectItems != null)
{
foreach (var item in selectItems)
{
listItemBuilder.AppendLine(ListItemToOption(item));
}
}
bool useGroup = selectList.All(m => m.Group != null);
if (useGroup)
{
foreach (var group in selectList.GroupBy(m => m.Group.Name))
{
IEnumerable<SelectListItem> items = selectList.Where(m => m.Group.Name == group.Key);
//< optgroup label = "German Cars" >
TagBuilder builder = new TagBuilder("optgroup");
if (!string.IsNullOrEmpty(group.Key))
{
builder.Attributes["label"] = group.Key;
}
foreach (SelectListItem item in items)
{
builder.InnerHtml = builder.InnerHtml + ListItemToOption(item);
}
listItemBuilder.Append(builder.ToString(TagRenderMode.Normal));
}
}
else
{
foreach (SelectListItem item in selectList)
{
listItemBuilder.AppendLine(ListItemToOption(item));
}
}
return listItemBuilder;
}
private static string ListItemToOption(SelectListItem item)
{
TagBuilder builder = new TagBuilder("option")
{
InnerHtml = HttpUtility.HtmlEncode(item.Text)
};
if (item.Value != null)
{
builder.Attributes["value"] = item.Value;
}
if (item.Selected)
{
builder.Attributes["selected"] = "selected";
}
return builder.ToString(TagRenderMode.Normal);
}
}
}