在Html.DropDownList中的 下添加html类标记

问题描述 投票:37回答:6

我一直在寻找有关如何在html.dropdownlist上添加HTML类标签的答案。这是代码

<%: Html.DropDownList("PackageId", new SelectList(ViewData["Packages"] as IEnumerable, "PackageId", "Name", Model.PackageId))%>

我想在select元素下添加选项的类,以便可以使用此链接的select:

<select id="category">
  <option value="1">One</option>
  <option value="2">Two</option>
</select>
<select id="package">
  <option value="1" class="1">One - package1</option>
  <option value="2" class="1">One - package2</option>
  <option value="3" class="2">Two - package1</option>
  <option value="4" class="2">Two - package2</option>
</select>

$("#series").chained("#mark");
html asp.net-mvc html-select
6个回答
52
投票

我已经为DropDownlistFor扩展方法完成了此操作,而不是您使用的DropDownList,但是您可能可以自己弄清楚。这些东西大部分是从MVC来源复制/粘贴的。您可以找到来源here

public class ExtendedSelectListItem : SelectListItem
{
    public object htmlAttributes { get; set; }
}

public static partial class HtmlHelperExtensions
{
    public static MvcHtmlString ExtendedDropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<ExtendedSelectListItem> selectList, string optionLabel, object htmlAttributes)
    {
        return SelectInternal(htmlHelper, optionLabel, ExpressionHelper.GetExpressionText(expression), selectList, false /* allowMultiple */, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
    }

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

        if (selectList == null)
            throw new ArgumentException("No selectlist");

        object defaultValue = (allowMultiple) ? GetModelStateValue(htmlHelper, fullName, typeof(string[])) : GetModelStateValue(htmlHelper, fullName, 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 (defaultValue == null)
            defaultValue = htmlHelper.ViewData.Eval(fullName);

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

            foreach (ExtendedSelectListItem 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
        StringBuilder listItemBuilder = new StringBuilder();

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

        foreach (ExtendedSelectListItem item in selectList)
        {
            listItemBuilder.Append(ListItemToOption(item));
        }

        TagBuilder tagBuilder = new TagBuilder("select")
        {
            InnerHtml = listItemBuilder.ToString()
        };
        tagBuilder.MergeAttributes(htmlAttributes);
        tagBuilder.MergeAttribute("name", fullName, true /* replaceExisting */);
        tagBuilder.GenerateId(fullName);
        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(fullName, out modelState))
        {
            if (modelState.Errors.Count > 0)
            {
                tagBuilder.AddCssClass(HtmlHelper.ValidationInputCssClassName);
            }
        }

        tagBuilder.MergeAttributes(htmlHelper.GetUnobtrusiveValidationAttributes(name));

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

    internal static string ListItemToOption(ExtendedSelectListItem 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";
        }
        builder.MergeAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(item.htmlAttributes));
        return builder.ToString(TagRenderMode.Normal);
    }
}

14
投票

这里是@ john-landheer解决方案的改进版本。

已改善:

  • 固定GetModelStateValue()的问题
  • 添加了[DropDownList()扩展方法
  • 不显眼的验证属性将按照应有的方式呈现

    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;
    
    namespace App.Infrastructure.Helpers
    {
        public class ExtendedSelectListItem : SelectListItem
        {
            public object HtmlAttributes { get; set; }
        }
    
        public static class ExtendedSelectExtensions
        {
            internal static object GetModelStateValue(this HtmlHelper htmlHelper, string key, Type destinationType)
            {
                System.Web.Mvc.ModelState modelState;
                if (htmlHelper.ViewData.ModelState.TryGetValue(key, out modelState))
                {
                    if (modelState.Value != null)
                    {
                        return modelState.Value.ConvertTo(destinationType, null /* culture */);
                    }
                }
                return null;
            }
    
            public static MvcHtmlString ExtendedDropDownList(this HtmlHelper htmlHelper, string name, IEnumerable<ExtendedSelectListItem> selectList)
            {
                return ExtendedDropDownList(htmlHelper, name, selectList, (string)null, (IDictionary<string, object>)null);
            }
    
            public static MvcHtmlString ExtendedDropDownList(this HtmlHelper htmlHelper, string name, IEnumerable<ExtendedSelectListItem> selectList, string optionLabel, IDictionary<string, object> htmlAttributes)
            {
                return ExtendedDropDownListHelper(htmlHelper, null, name, selectList, optionLabel, htmlAttributes);
            }
    
            public static MvcHtmlString ExtendedDropDownListHelper(this HtmlHelper htmlHelper, ModelMetadata metadata, string expression, IEnumerable<ExtendedSelectListItem> selectList, string optionLabel, IDictionary<string, object> htmlAttributes)
            {
                return SelectInternal(htmlHelper, metadata, optionLabel, expression, selectList, false, htmlAttributes);
            }
    
            public static MvcHtmlString ExtendedDropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper,
                Expression<Func<TModel, TProperty>> expression, IEnumerable<ExtendedSelectListItem> selectList,
                string optionLabel, object htmlAttributes)
            {
                if (expression == null)
                    throw new ArgumentNullException("expression");
                ModelMetadata metadata = ModelMetadata.FromLambdaExpression<TModel, TProperty>(expression, htmlHelper.ViewData);
                return SelectInternal(htmlHelper, metadata, optionLabel, ExpressionHelper.GetExpressionText(expression), selectList,
                    false /* allowMultiple */, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
            }
    
            private static MvcHtmlString SelectInternal(this HtmlHelper htmlHelper, ModelMetadata metadata, string optionLabel, string name,
                IEnumerable<ExtendedSelectListItem> selectList, bool allowMultiple,
                IDictionary<string, object> htmlAttributes)
            {
                string fullName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
                if (String.IsNullOrEmpty(fullName))
                    throw new ArgumentException("No name");
    
                if (selectList == null)
                    throw new ArgumentException("No selectlist");
    
                object defaultValue = (allowMultiple)
                    ? htmlHelper.GetModelStateValue(fullName, typeof(string[]))
                    : htmlHelper.GetModelStateValue(fullName, 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 (defaultValue == null)
                    defaultValue = htmlHelper.ViewData.Eval(fullName);
    
                if (defaultValue != null)
                {
                    IEnumerable defaultValues = (allowMultiple) ? defaultValue as IEnumerable : new[] { defaultValue };
                    IEnumerable<string> values = from object value in defaultValues
                                                 select Convert.ToString(value, CultureInfo.CurrentCulture);
                    HashSet<string> selectedValues = new HashSet<string>(values, StringComparer.OrdinalIgnoreCase);
                    List<ExtendedSelectListItem> newSelectList = new List<ExtendedSelectListItem>();
    
                    foreach (ExtendedSelectListItem 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
                StringBuilder listItemBuilder = new StringBuilder();
    
                // Make optionLabel the first item that gets rendered.
                if (optionLabel != null)
                    listItemBuilder.Append(
                        ListItemToOption(new ExtendedSelectListItem()
                        {
                            Text = optionLabel,
                            Value = String.Empty,
                            Selected = false
                        }));
    
                foreach (ExtendedSelectListItem item in selectList)
                {
                    listItemBuilder.Append(ListItemToOption(item));
                }
    
                TagBuilder tagBuilder = new TagBuilder("select")
                {
                    InnerHtml = listItemBuilder.ToString()
                };
                tagBuilder.MergeAttributes(htmlAttributes);
                tagBuilder.MergeAttribute("name", fullName, true /* replaceExisting */);
                tagBuilder.GenerateId(fullName);
                if (allowMultiple)
                    tagBuilder.MergeAttribute("multiple", "multiple");
    
                // If there are any errors for a named field, we add the css attribute.
                System.Web.Mvc.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 MvcHtmlString.Create(tagBuilder.ToString(TagRenderMode.Normal));
            }
    
            internal static string ListItemToOption(ExtendedSelectListItem 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";
                }
                builder.MergeAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(item.HtmlAttributes));
                return builder.ToString(TagRenderMode.Normal);
            }
    
        }
    }
    

5
投票

使用ASP.NET MVC内置的DropDownList帮助器是不可能的。因此,如果需要,您将必须编写自己的帮助程序。您可以看一下使用TagBuilder生成选项的ASP.NET MVC的源代码,还可以在自定义实现中附加任何属性。另一个不太优雅的解决方案是手动遍历视图中的数据集并生成单个选项元素。


2
投票

首先想到的是JQuery。您可以使用以下代码轻松完成此操作:

$("#bla").find("option").addClass("poo");

1
投票

一个简单的解决方案:当您添加

@Html.DropDownList("someID", new SelectList(Model.selectItems),"--Select--",new { @class= "select-ddl" })

在CSS中再添加一个类,作为

.select-ddl option {}

此类将应用于HTML中的所有选项标签。


0
投票

我写了一个只修改html的包装器:

    public static MvcHtmlString DisableFirstItem(MvcHtmlString htmlString)
    {
        return new MvcHtmlString(
            htmlString.ToString()
            .Replace("<option value=\"Unknown\">", 
                     "<option disabled value=\"Unknown\">")
        );
    }

然后我用这个辅助函数包装了我的DropDownListFor:

        @Html.Raw(MyHtmlHelpers.DisableFirstItem(

          Html.DropDownListFor(m => m.Instrument,
            new SelectList(ReflectionHelpers.GenerateEnumDictionary<OrderInstrument>(true), "Key", "Value", Model.Instrument),
            new { @class = "form-control" })

        ))

如果您愿意,显然可以使助手功能更加复杂。

© www.soinside.com 2019 - 2024. All rights reserved.