在下拉列表.NET MVC中支持optgroup?

Kev*_*nUK 63 asp.net-mvc drop-down-menu

继续以编程方式创建下拉列表的这个问题,我希望我的列表也有几个optgroup列表.这目前可能吗?

我知道我需要将selectList传递给dropDownList,但不知道如何将文本,值,optgroup添加到selectList.

我希望最终结果产生:

<option value="">Please select</option>
  <optgroup label="Option A">
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
    <option value="4">4</option>
  </optgroup>
  <optgroup label="Option B">
    <option value="a">A</option>
    <option value="b">B</option>
    <option value="c">C</option>
  </optgroup>
</option>
Run Code Online (Sandbox Code Playgroud)

小智 92

我的扩展有点复杂,但它具有原始DropDownList所有的重载.

实际上我已经专门创建它以便能够使用组生成DropDownList并在jDoubleSelect的帮助下转换为两个连接的选择

using System;using System.Collections;using System.Collections.Generic;using System.Globalization; using System.Linq;using System.Linq.Expressions;using System.Text; using System.Web;using System.Web.Mvc;using System.Web.Routing;

public class GroupedSelectListItem : SelectListItem
{
    public string GroupKey { get; set; }
    public string GroupName { get; set; }
}

public static class HtmlHelpers
{
    public static MvcHtmlString DropDownGroupList(this HtmlHelper htmlHelper, string name)
    {
        return DropDownListHelper(htmlHelper, name, null, null, null);
    }

    public static MvcHtmlString DropDownGroupList(this HtmlHelper htmlHelper, string name, IEnumerable<GroupedSelectListItem> selectList)
    {
        return DropDownListHelper(htmlHelper, name, selectList, null, null);
    }

    public static MvcHtmlString DropDownGroupList(this HtmlHelper htmlHelper, string name, string optionLabel)
    {
        return DropDownListHelper(htmlHelper, name, null, optionLabel, null);
    }

    public static MvcHtmlString DropDownGroupList(this HtmlHelper htmlHelper, string name, IEnumerable<GroupedSelectListItem> selectList, IDictionary<string, object> htmlAttributes)
    {
        return DropDownListHelper(htmlHelper, name, selectList, null, htmlAttributes);
    }

    public static MvcHtmlString DropDownGroupList(this HtmlHelper htmlHelper, string name, IEnumerable<GroupedSelectListItem> selectList, object htmlAttributes)
    {
        return DropDownListHelper(htmlHelper, name, selectList, null, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
    }

    public static MvcHtmlString DropDownGroupList(this HtmlHelper htmlHelper, string name, IEnumerable<GroupedSelectListItem> selectList, string optionLabel)
    {
        return DropDownListHelper(htmlHelper, name, selectList, optionLabel, null);
    }

    public static MvcHtmlString DropDownGroupList(this HtmlHelper htmlHelper, string name, IEnumerable<GroupedSelectListItem> selectList, string optionLabel, IDictionary<string, object> htmlAttributes)
    {
        return DropDownListHelper(htmlHelper, name, selectList, optionLabel, htmlAttributes);
    }

    public static MvcHtmlString DropDownGroupList(this HtmlHelper htmlHelper, string name, IEnumerable<GroupedSelectListItem> selectList, string optionLabel, object htmlAttributes)
    {
        return DropDownListHelper(htmlHelper, name, selectList, optionLabel, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
    }

    public static MvcHtmlString DropDownGroupListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<GroupedSelectListItem> selectList)
    {
        return DropDownGroupListFor(htmlHelper, expression, selectList, null /* optionLabel */, null /* htmlAttributes */);
    }

    public static MvcHtmlString DropDownGroupListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<GroupedSelectListItem> selectList, object htmlAttributes)
    {
        return DropDownGroupListFor(htmlHelper, expression, selectList, null /* optionLabel */, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
    }

    public static MvcHtmlString DropDownGroupListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<GroupedSelectListItem> selectList, IDictionary<string, object> htmlAttributes)
    {
        return DropDownGroupListFor(htmlHelper, expression, selectList, null /* optionLabel */, htmlAttributes);
    }

    public static MvcHtmlString DropDownGroupListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<GroupedSelectListItem> selectList, string optionLabel)
    {
        return DropDownGroupListFor(htmlHelper, expression, selectList, optionLabel, null /* htmlAttributes */);
    }

    public static MvcHtmlString DropDownGroupListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<GroupedSelectListItem> selectList, string optionLabel, object htmlAttributes)
    {
        return DropDownGroupListFor(htmlHelper, expression, selectList, optionLabel, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
    }

    public static MvcHtmlString DropDownGroupListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<GroupedSelectListItem> selectList, string optionLabel, IDictionary<string, object> htmlAttributes)
    {
        if (expression == null)
        {
            throw new ArgumentNullException("expression");
        }

        return DropDownListHelper(htmlHelper, ExpressionHelper.GetExpressionText(expression), selectList, optionLabel, htmlAttributes);
    }

    private static MvcHtmlString DropDownListHelper(HtmlHelper htmlHelper, string expression, IEnumerable<GroupedSelectListItem> selectList, string optionLabel, IDictionary<string, object> htmlAttributes)
    {
        return SelectInternal(htmlHelper, optionLabel, expression, selectList, false /* allowMultiple */, htmlAttributes);
    }


    // Helper methods

    private static IEnumerable<GroupedSelectListItem> GetSelectData(this HtmlHelper htmlHelper, string name)
    {
        object o = null;
        if (htmlHelper.ViewData != null)
        {
            o = htmlHelper.ViewData.Eval(name);
        }
        if (o == null)
        {
            throw new InvalidOperationException(
                String.Format(
                    CultureInfo.CurrentCulture,
                    "Missing Select Data"));
        }
        var selectList = o as IEnumerable<GroupedSelectListItem>;
        if (selectList == null)
        {
            throw new InvalidOperationException(
                String.Format(
                    CultureInfo.CurrentCulture,
                    "Wrong Select DataType"));
        }
        return selectList;
    }

    internal static string ListItemToOption(GroupedSelectListItem item)
    {
        var 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);
    }

    private static MvcHtmlString SelectInternal(this HtmlHelper htmlHelper, string optionLabel, string name, IEnumerable<GroupedSelectListItem> selectList, bool allowMultiple, IDictionary<string, object> htmlAttributes)
    {
        name = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
        if (String.IsNullOrEmpty(name))
        {
            throw new ArgumentException("Null Or Empty", "name");
        }

        bool usedViewData = false;

        // If we got a null selectList, try to use ViewData to get the list of items.
        if (selectList == null)
        {
            selectList = htmlHelper.GetSelectData(name);
            usedViewData = true;
        }

        object defaultValue = (allowMultiple) ? htmlHelper.GetModelStateValue(name, typeof(string[])) : htmlHelper.GetModelStateValue(name, typeof(string));

        // If we haven't already used ViewData to get the entire list of items then we need to
        // use the ViewData-supplied value before using the parameter-supplied value.
        if (!usedViewData)
        {
            if (defaultValue == null)
            {
                defaultValue = htmlHelper.ViewData.Eval(name);
            }
        }

        if (defaultValue != null)
        {
            var defaultValues = (allowMultiple) ? defaultValue as IEnumerable : new[] { defaultValue };
            var values = from object value in defaultValues select Convert.ToString(value, CultureInfo.CurrentCulture);
            var selectedValues = new HashSet<string>(values, StringComparer.OrdinalIgnoreCase);
            var newSelectList = new List<GroupedSelectListItem>();

            foreach (var item in selectList)
            {
                item.Selected = (item.Value != null) ? selectedValues.Contains(item.Value) : selectedValues.Contains(item.Text);
                newSelectList.Add(item);
            }
            selectList = newSelectList;
        }

        // Convert each ListItem to an <option> tag
        var listItemBuilder = new StringBuilder();

        // Make optionLabel the first item that gets rendered.
        if (optionLabel != null)
        {
            listItemBuilder.AppendLine(ListItemToOption(new GroupedSelectListItem { Text = optionLabel, Value = String.Empty, Selected = false }));
        }

        foreach (var group in selectList.GroupBy(i => i.GroupKey))
        {
            string groupName = selectList.Where(i => i.GroupKey == group.Key).Select(it => it.GroupName).FirstOrDefault();
            listItemBuilder.AppendLine(string.Format("<optgroup label=\"{0}\" value=\"{1}\">", groupName, group.Key));
            foreach (GroupedSelectListItem item in group)
            {
                listItemBuilder.AppendLine(ListItemToOption(item));
            }
            listItemBuilder.AppendLine("</optgroup>");
        }

        var tagBuilder = new TagBuilder("select")
        {
            InnerHtml = listItemBuilder.ToString()
        };
        tagBuilder.MergeAttributes(htmlAttributes);
        tagBuilder.MergeAttribute("name", name, true /* replaceExisting */);
        tagBuilder.GenerateId(name);
        if (allowMultiple)
        {
            tagBuilder.MergeAttribute("multiple", "multiple");
        }

        // If there are any errors for a named field, we add the css attribute.
        ModelState modelState;
        if (htmlHelper.ViewData.ModelState.TryGetValue(name, out modelState))
        {
            if (modelState.Errors.Count > 0)
            {
                tagBuilder.AddCssClass(HtmlHelper.ValidationInputCssClassName);
            }
        }

        return MvcHtmlString.Create(tagBuilder.ToString());
    }

    internal static object GetModelStateValue(this HtmlHelper helper, string key, Type destinationType)
    {
        ModelState modelState;
        if (helper.ViewData.ModelState.TryGetValue(key, out modelState))
        {
            if (modelState.Value != null)
            {
                return modelState.Value.ConvertTo(destinationType, null /* culture */);
            }
        }
        return null;
    }

}
Run Code Online (Sandbox Code Playgroud)

  • 可以在此处找到示例用法:http://stackoverflow.com/a/8852941/304832 (3认同)

Dan*_*olm 36

这是在5.2版本的ASP.Net MVC中添加的,现在是内置的.

SelectListItem上Group属性允许您为每个项目指定一个组:

新的SelectList构造函数还允许您在提供的项列表中提供包含组标题的字段的名称.

HtmlHelper DropDownList和DropDownListFor方法现在根据项目列表中包含的组生成optgroup元素.

简单!

  • 是啊!这里一个例子:http://qiita.com/rryu/items/0fdfde55a62a44f0add0 VAR项=新列表<SelectListItem>(); var group1 = new SelectListGroup(){Name ="Group 1"}; items.Add(new SelectListItem(){Text ="Item1",Group = group1}); 和@ Html.DropDownList("选择",项目) (4认同)

小智 25

我只是写了一个扩展来做到这一点,看到它:


using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Routing;

namespace System.Web.Mvc.Html
{
    public static class GroupDropListExtensions
    {
        public static string GroupDropList(this HtmlHelper helper, string name, IEnumerable<GroupDropListItem> data, string SelectedValue, object htmlAttributes)
        {
            if (data == null && helper.ViewData != null)
                data = helper.ViewData.Eval(name) as IEnumerable<GroupDropListItem>;
            if (data == null) return string.Empty;

            var select = new TagBuilder("select");

            if (htmlAttributes != null)
                select.MergeAttributes(new RouteValueDictionary(htmlAttributes));

            select.GenerateId(name);

            var optgroupHtml = new StringBuilder();
            var groups = data.ToList();
            foreach (var group in data)
            {
                var groupTag = new TagBuilder("optgroup");
                groupTag.Attributes.Add("label", helper.Encode( group.Name));
                var optHtml = new StringBuilder();
                foreach (var item in group.Items)
                {
                    var option = new TagBuilder("option");
                    option.Attributes.Add("value", helper.Encode(item.Value));
                    if (SelectedValue != null && item.Value == SelectedValue)
                        option.Attributes.Add("selected", "selected");
                    option.InnerHtml = helper.Encode(item.Text);
                    optHtml.AppendLine(option.ToString(TagRenderMode.Normal));
                }
                groupTag.InnerHtml = optHtml.ToString();
                optgroupHtml.AppendLine(groupTag.ToString(TagRenderMode.Normal));
            }
            select.InnerHtml = optgroupHtml.ToString();
            return select.ToString(TagRenderMode.Normal);
        }
}

    public class GroupDropListItem
    {
        public string Name { get; set; }
        public List<OptionItem> Items { get; set; }
    }

    public class OptionItem
    {
        public string Text { get; set; }
        public string Value { get; set; }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 请参阅http://stackoverflow.com/questions/4142986/optgroup-drop-down-support-in-mvc-problems-with-model-binding,以便对代码进行细微更改,因为我无法使其工作. .. 谢谢. (4认同)

tva*_*son 13

查看www.codeplex.com/aspnet上的代码,似乎没有SelectList和DropDownList扩展方法都支持在select中使用OptGroup.看起来您需要编写自己的扩展方法并扩展SelectListItem以包含分组或在标记中手动生成选择.