Search code examples
asp.net-mvchtml-helper

Creating a SelectListItem with the disabled="disabled" attribute


I'm not seeing a way to create, via the HtmlHelper, a SelectListItem that will spit out the following HTML:

<option disabled="disabled">don't click this</option>

The only properties SelectListItem has are:

new SelectListItem{
  Name = "don't click this",
  Value = string.Empty,
  Selected = false
}

The only option I see is to

  1. Subclass the SelectListItem to add an Enabled property to get the value to the view
  2. Not use the HTML helper for DropDownList
  3. Create a new HtmlHelper extension that accepts my new EnablableSelectList and adds my disabled attribute.

Solution

  • This is something I might try before recreating the helper completely. The basic idea is that the Html you get from the helper should be well formed, so it should be safe to parse. So you can build on that idea by making your own extension that uses the existing extension but adds the functionality to disable the items.

    Something like this might do (totally untested)

    public class CustomSelectItem : SelectListItem
    {
        public bool Enabled { get; set; }
    }
    
    public static class CustomHtmlHelpers
    {
        public static MvcHtmlString MyDropDownList(this HtmlHelper html, IEnumerable<CustomSelectItem> selectList)
        {
            var selectDoc = XDocument.Parse(html.DropDownList("", (IEnumerable<SelectListItem>)selectList).ToString());
    
            var options = from XElement el in selectDoc.Element("select").Descendants()
                                        select el;
    
            foreach (var item in options)
            {
                var itemValue = item.Attribute("value");
                if (!selectList.Where(x => x.Value == itemValue.Value).Single().Enabled)
                    item.SetAttributeValue("disabled", "disabled");
            }
    
            // rebuild the control, resetting the options with the ones you modified
            selectDoc.Root.ReplaceNodes(options.ToArray());
            return MvcHtmlString.Create(selectDoc.ToString());
        }
    }