Search code examples
asp.net-mvcasp.net-mvc-3html-helperhtml.listboxfor

MVC Method to output unordered list from the ListBoxFor method


In MVC3, I want to change the HTML output by the Html.ListBoxFor method so that instead of an HTML list box with all the available values (and the selected values highlighted), I want to simply output an unordered list (UL, LI) of the selected items and not a SELECT element. The issue is that I want to keep exactly the same method signature as the ListBoxFor method, accepting a MultiSelectList object and a List which is the selected values. I then want the unordered list to only output the selected item values (not keys) as UL/LI html. Here is the method signature I would like to have. How can this be accomplished?

public static MvcHtmlString ListBoxForAsUnorderedList <TModel, TProperty>
    (this HtmlHelper<TModel> htmlHelper, 
          Expression<Func<TModel, TProperty>> expression, 
          IEnumerable<SelectListItem> selectList)

Solution

  • I figured this out and the code is below in case it helps anyone else out. Basically, I passed the parameters to the generic ListBox method, getting back the raw HTML generated and then used Linq to XML to grab only the "selected" values into a string array. I then looped through the string array and used a TagBuilder("ul") to generate the list. I am open to any comments or criticisms about using this method.

    public static MvcHtmlString ListBoxForAsUnorderedList<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<SelectListItem> selectList)
    {
      var mvcHtmlString = System.Web.Mvc.Html.SelectExtensions.ListBox(htmlHelper, ExpressionHelper.GetExpressionText(expression), selectList, null);
      var selectedValues = XDocument.Parse(mvcHtmlString.ToHtmlString()).Descendants("option").Where(e => (string)e.Attribute("selected") == "selected").Select(e => e.Value).ToArray();
      var tag = new TagBuilder("ul");
      foreach (var value in selectedValues)
      {
        var itemTag = new TagBuilder("li");
        itemTag.SetInnerText(value);
        tag.InnerHtml += itemTag.ToString();
      }
      return new MvcHtmlString(tag.ToString());
    }