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);
        }
    }
}
posted @ 2017-02-22 19:00  烽火情怀  阅读(439)  评论(0编辑  收藏  举报