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

pau*_*aul 36 html asp.net-mvc html-select

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

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

我想在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");
Run Code Online (Sandbox Code Playgroud)

Joh*_*eer 51

我已经为DropDownlistFor扩展方法做了这个,而不是你使用的DropDownList,但是你可以自己解决这个问题.这些东西主要是来自MVC源的复制/粘贴.你可以在这里找到来源.

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这真的很好,除了缺少GetModelStateValue()方法(现在是?)内部.这个问题涵盖了这个问题:http://stackoverflow.com/questions/6967148/not-able-to-access-getmodelstatevalue-in-custom-control-in-asp-net-mvc2 (10认同)
  • 对于那些遇到GetModelStateValue()问题的人,在Github上共享的这段代码中使用GetModelStateValue()的方法定义(只需复制粘贴到HtmlHelperExtensions)解决了这个问题:[Eleven41.Web.Mvc.Bootstrap Github](https:// github. COM/bbickett/Eleven41.Web.Mvc.Bootstrap /斑点/主/ Eleven41.Web.Mvc.Bootstrap/InputExtensions.cs) (3认同)
  • 这是更正的行:`object defaultValue =(allowMultiple)?htmlHelper.GetModelStateValue(fullName,typeof(string [])):htmlHelper.GetModelStateValue(fullName,typeof(string));` (2认同)

Ale*_*kov 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);
            }
    
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)


Dar*_*rov 5

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

  • 知道是否在较新版本的框架(5.2.3)中进行了介绍?很遗憾,您必须编写自定义代码才能实现相当常见的使用行为:( (2认同)

tug*_*erk 2

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

$("#bla").find("option").addClass("poo");
Run Code Online (Sandbox Code Playgroud)

  • 我不能那样做。我需要类来更改我的链接选择的值。 (2认同)