Question

Using the sample explanation found on MSDN for:

SelectList Class (http://msdn.microsoft.com/en-us/library/system.web.mvc.selectlist_members(v=vs.90).aspx)

SelectListItem (http://msdn.microsoft.com/en-us/library/system.web.mvc.multiselectlist.items(v=vs.90).aspx)

And IEnumerable (http://msdn.microsoft.com/en-us/library/system.collections.ienumerable(v=vs.90).aspx)

I have created the following classes from the sample Person/People code.

Public Class Choice
  '
  Private _Value As String = Nothing
  Private _Text As String = Nothing
  Private _Selected As Boolean = Nothing
  '
  Property ItemValue As String
    Get
      Return _Value
    End Get
    Set(value As String)
      _Value = value
    End Set
  End Property
  '
  Property ItemText As String
    Get
      Return _Text
    End Get
    Set(value As String)
      _Text = value
    End Set
  End Property
  '
  Property ItemSelected As Boolean
    Get
      Return _Selected
    End Get
    Set(value As Boolean)
      _Selected = value
    End Set
  End Property
  '
  Public Sub New(ByVal pValue As String, ByVal pText As String)
    Me._Value = pValue
    Me._Text = pText
    Me._Selected = False
  End Sub
  '
  Public Sub New(ByVal pValue As String, ByVal pText As String, pSelected As Boolean)
    Me._Value = pValue
    Me._Text = pText
    Me._Selected = pSelected
  End Sub
'
End Class


Public Class Choices
  Implements IEnumerable
  '
  Private _Choices() As Choice
  '
  Public ReadOnly Property SelectedValue() As Choice
    Get
      Dim i As Integer = Nothing
      Dim x As Choice = Nothing
      For i = 0 To _Choices.Length - 1
        If _Choices(i).ItemSelected Then
          x = _Choices(i)
          Exit For
        End If
      Next i
      Return x
      i = Nothing
      x = Nothing
    End Get
  End Property
  '
  Public Sub New(ByVal pArray() As Choice)
    _Choices = New Choice(pArray.Length - 1) {}
    Dim i As Integer
      For i = 0 To pArray.Length - 1
        _Choices(i) = pArray(i)
      Next i
  End Sub
  '
  Public Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
    Return New ChoicesEnum(_Choices)
  End Function
  '
End Class


Public Class ChoicesEnum
  Implements IEnumerator
  '
  Public _Choices() As Choice
  '
  Dim position As Integer = -1
  '
  Public Sub New(ByVal list() As Choice)
    _Choices = list
  End Sub
  '
  Public Function MoveNext() As Boolean Implements IEnumerator.MoveNext
    position = position + 1
    Return (position < _Choices.Length)
  End Function
  '
  Public Sub Reset() Implements IEnumerator.Reset
    position = -1
  End Sub
  '
  Public ReadOnly Property Current() As Object Implements IEnumerator.Current
    Get
      Try
        Return _Choices(position)
      Catch ex As IndexOutOfRangeException
        Throw New InvalidOperationException()
      End Try
    End Get
  End Property
  '
End Class

In my model I have declared it as follows

Private _Gender As Integer = Nothing

In my controller I instantiate a selectlist as follows:

Friend Function GetGenderList(SelId As Integer) As SelectList
  '
  Dim ChoicesArray() As Choice = { _
    New Choice("0", "Please Select Gender", IIf(SelId = 0, True, False)), _
    New Choice("1", "Male", IIf(SelId = 1, True, False)), _
    New Choice("2", "Female", IIf(SelId = 2, True, False)), _
    New Choice("3", "Unspecified", IIf(SelId = 3, True, False))}
  Dim ChoicesList As New Choices(ChoicesArray)
    GetGenderList = New SelectList(ChoicesList, ChoicesList(SelId))
    ChoicesList = Nothing
    ChoicesArray = Nothing
    '
End Function

Then I pass the selectlist in the viewdata to the view

<ChildActionOnly()> _
Function EditPersonalUserCtrl(ByVal MyPersonal As MemberPersonalModel, FoundErrorInfo As String) As PartialViewResult
  Dim sxGenderList As SelectList = Nothing
  sxGenderList = GetGenderList(MyPersonal.Gender)
  ViewData.Add("Gender", sxGenderList)
  ViewData.Add("FoundErrorInfo", FoundErrorInfo)
  Return PartialView(MyPersonal)
  sxGenderList = Nothing
End Function 

In my view the html is as follows

<tr>
  <td class="FormFieldLabel" style="width: 30%;">Gender</td>
  <td class="FormFieldLabel" style="width: 70%;">
    <%= Html.DropDownListFor(Function(Model) Model.Gender, New SelectList(ViewData("Gender").Items, "ItemValue", "ItemText", "ItemSelected"), New With {.style = "font-family: Tahoma; font-size: 14pt; color: #333333;"})%>
    <%= Html.ValidationMessageFor(Function(Model) Model.Gender)%>
  </td>
</tr>

When I try the view in EDIT/UPDATE the SelectList/DropDown always shows the FIRST option item in the list, regardless or whats selected.

Its baffled me for two days and I cannot see where its going wrong! Please can someone take a look at my code and see where its going west.

Thanks in advance.

Was it helpful?

Solution

After trying various approaches I thought the best solution was to write my own SelectListExtension.

The Extension I wrote is based around the "Choice", "Choices" and "ChoicesEnum" classes.

Public Module ChoicesListExtension

  <Extension()>
  Public Function DropDownListFor(ByVal ObjSelectList As Choices, ByVal HtmlCtrlId As String) As String
    '
    Dim Buf As String = Nothing
    Dim Counter1 As Integer = Nothing
    '
    Buf = ""
    If (ObjSelectList Is Nothing) = False Then
      If Trim(HtmlCtrlId) <> "" Then
        Buf = "<select id=" & Chr(34) & Trim(HtmlCtrlId) & Chr(34) & ">" & vbCrLf
      Else
        Buf = "<select>" & vbCrLf
      End If
      If ObjSelectList.Items.Count > 0 Then
        For Counter1 = 0 To ObjSelectList.Items.Count - 1
          Buf = Buf & "  <option value=" & Chr(34) & ObjSelectList(Counter1).ItemValue Chr(34)
            If ObjSelectList(Counter1).ItemSelected Then Buf = Buf & " selected=" & Chr(34) & "selected" & Chr(34)
          Buf = Buf & ">" & Trim(ObjSelectList(Counter1).ItemText) & "</option>" & vbCrLf
        Next
      End If
      Buf = Buf & "</select>" & vbCrLf
    End If
    DropDownListFor = Buf
    Buf = Nothing
    Counter1 = Nothing
    '
  End Function





  <Extension()>
  Public Function DropDownListFor(ByVal ObjSelectList As Choices, ByVal HtmlCtrlId As String, ByVal HtmlAttribs As RouteValueDictionary) As String
  '
  Dim Buf As String = Nothing
  Dim Counter1 As Integer = Nothing
  Dim Counter2 As Integer = Nothing
    '
    Buf = ""
    If (ObjSelectList Is Nothing) = False Then
      If Trim(HtmlCtrlId) <> "" Then
        Buf = "<select id=" & Chr(34) & Trim(HtmlCtrlId) & Chr(34)
        If HtmlAttribs.Count > 0 Then
          For Counter1 = 0 To HtmlAttribs.Count - 1
            Buf = Buf & " " & HtmlAttribs.Keys(Counter1) & "=" & Chr(34) & HtmlAttribs.Values(Counter1) & Chr(34)
          Next
        End If
        Buf = Buf & ">" & vbCrLf
      Else
        Buf = "<select>" & vbCrLf
      End If
      If ObjSelectList.Items.Count > 0 Then
        For Counter2 = 0 To ObjSelectList.Items.Count - 1
          Buf = Buf & "  <option value=" & Chr(34) & ObjSelectList(Counter2).ItemValue & Chr(34)
          If ObjSelectList(Counter2).ItemSelected Then Buf = Buf & " selected=" & Chr(34) & "selected" & Chr(34)
          Buf = Buf & ">" & Trim(ObjSelectList(Counter2).ItemText) & "</option>" & vbCrLf
        Next
      End If
      Buf = Buf & "</select>" & vbCrLf
    End If
    DropDownListFor = Buf
    Buf = Nothing
    Counter1 = Nothing
    Counter2 = Nothing
    '
  End Function

End Module
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top