Results 1 to 1 of 1

Thread: ASP.NET MVC ListBoxFor() with optgroup Tag support

Threaded View

  1. #1

    Thread Starter
    Frenzied Member KGComputers's Avatar
    Join Date
    Dec 2005
    Location
    Cebu, PH
    Posts
    2,020

    ASP.NET MVC ListBoxFor() with optgroup Tag support

    Hello,

    By default, ASP.NET MVC ListBoxFor() helper does not have support for optgroup tag. To achieve this functionality, we either use jQuery or create a custom html helper. The example below demonstrates using the latter and is a VB.NET version of what we have developed in C#.

    First, we define our ViewModel class for the countries with states and selected states.
    VB.NET Code:
    1. Public Class CountriesStatesViewModel
    2.     Public Property SelectedStates() As IEnumerable(Of String)
    3.     Public Property CountriesAndStates() As Dictionary(Of String, IEnumerable(Of SelectListItem))
    4. End Class

    Next, we create the custom ListBoxFor() helper that supports optgroup tag.
    VB.NET Code:
    1. Public Module HtmlExtensions
    2.  
    3.     <Extension()>
    4.     Public Function ListBoxFor(Of TModel, TProperty)(htmlHelper As HtmlHelper(Of TModel), expression As Expression(Of Func(Of TModel, TProperty)), _
    5.         selectList As Dictionary(Of String, IEnumerable(Of SelectListItem)), Optional htmlAttributes As Object = Nothing) As IHtmlString
    6.  
    7. Dim selectTag = New TagBuilder("select")
    8.         selectTag.Attributes.Add("name", ExpressionHelper.GetExpressionText(expression))
    9.  
    10.         If htmlAttributes IsNot Nothing Then
    11.             Dim routeValues As New RouteValueDictionary(htmlAttributes)
    12.             If Not routeValues.ContainsKey(("size").ToLower()) Then
    13.                 selectTag.Attributes.Add("size", selectList.Sum(Function(x) x.Value.Count()).ToString())
    14.             End If
    15.  
    16.             For Each item In routeValues
    17.                 selectTag.Attributes.Add(item.Key, item.Value.ToString())
    18.             Next
    19.         Else
    20.             selectTag.Attributes.Add("size", selectList.Sum(Function(x) x.Value.Count()).ToString())
    21.         End If
    22.  
    23.         Dim optgroups = New StringBuilder()
    24.  
    25.         For Each kvp In selectList
    26.             Dim optgroup = New TagBuilder("optgroup")
    27.             optgroup.Attributes.Add("label", kvp.Key)
    28.  
    29.             Dim options = New StringBuilder()
    30.  
    31.             For Each item In kvp.Value
    32.                 Dim optionTag = New TagBuilder("option")
    33.  
    34.                 optionTag.Attributes.Add("value", item.Value)
    35.                 optionTag.SetInnerText(item.Text)
    36.  
    37. If item.Selected Then
    38.                     optionTag.Attributes.Add("selected", "selected")
    39.                 End If
    40.  
    41.                 options.Append(optionTag.ToString(TagRenderMode.Normal))
    42.             Next
    43.  
    44.             optgroup.InnerHtml = options.ToString()
    45.  
    46.             optgroups.Append(optgroup.ToString(TagRenderMode.Normal))
    47.         Next
    48.  
    49.         selectTag.InnerHtml = optgroups.ToString()
    50.  
    51.         Return MvcHtmlString.Create(selectTag.ToString(TagRenderMode.Normal))
    52.  
    53.  
    54.     End Function
    55. End Module

    In our controller, we add two action result methods. The Index action adds data to our model and then pass it to our view for rendering. The SaveEntry action retrieves the selected states chosen by the user.

    VB.NET Code:
    1. Function Index() As ActionResult
    2.     Dim model As New CountriesStatesViewModel
    3.     Dim items As New Dictionary(Of String, IEnumerable(Of SelectListItem))
    4.     model.CountriesAndStates = New Dictionary(Of String, IEnumerable(Of SelectListItem))
    5.  
    6.  
    7.     items.Add("US", New List(Of SelectListItem)() From { _
    8.         New SelectListItem() With {.Text = "Arizona", .Value = "001", .Selected = False},
    9.         New SelectListItem() With {.Text = "Montana", .Value = "002", .Selected = False}
    10.     })
    11.  
    12.  
    13.     items.Add("AU", New List(Of SelectListItem)() From { _
    14.         New SelectListItem() With {.Text = "Queensland", .Value = "003", .Selected = False},
    15.         New SelectListItem() With {.Text = "Victoria", .Value = "004", .Selected = False}
    16.     })
    17.  
    18.  
    19.     items.Add("BR", New List(Of SelectListItem)() From { _
    20.         New SelectListItem() With {.Text = "Bahia", .Value = "005", .Selected = False},
    21.         New SelectListItem() With {.Text = "Minas Gerais", .Value = "006", .Selected = False}
    22.     })
    23.  
    24.  
    25.     model.CountriesAndStates = items
    26.  
    27.  
    28.     Return View(model)
    29. End Function
    30.  
    31.  
    32. <HttpPost>
    33. Function SaveEntry(SelectedStates As IEnumerable(Of String)) As ActionResult
    34.     'get selected states
    35.     If SelectedStates IsNot Nothing Then
    36.         If SelectedStates.Count() > 0 Then
    37.             TempData("list") = SelectedStates.ToList() 'replace with your own code
    38.             Return RedirectToAction("SelectionSuccess") 'replace with your own code
    39.         End If
    40.     End If
    41.  
    42.  
    43.     Return RedirectToAction("Index") 'replace with your own code
    44. End Function

    And in our view (Index.vbhtml), make sure to reference the ViewModel class and Helper.
    HTML Code:
    1. @ModelType ASPMVCListBoxForHelper.CountriesStatesViewModel
    2. @Imports ASPMVCListBoxForHelper.Helpers
    3. <div>
    4.     @Using Html.BeginForm("SaveEntry", "Home", FormMethod.Post)
    5.         @Html.ListBoxFor(Function(t) t.SelectedStates, Model.CountriesAndStates, New With {.Multiple = "Multiple", .Size = Model.CountriesAndStates.Sum(Function(x) x.Value.Count())})
    6.         @<br />
    7.         @<input name="Save" type="submit" value="Save" />
    8.     End Using
    9. </div>

    Screenshot
    Name:  ListBoxForOptGroup.PNG
Views: 2073
Size:  3.6 KB

    Source code: VB.NET Version|C# Version

    That's it.. :-)
    Last edited by KGComputers; Mar 14th, 2017 at 12:46 AM. Reason: added github link
    CodeBank: VB.NET & C#.NET | ASP.NET
    Programming: C# | VB.NET
    Blogs: Personal | Programming
    Projects: GitHub | jsFiddle
    ___________________________________________________________________________________

    Rating someone's post is a way of saying Thanks...

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width