Search code examples
c#vb.netwinformscomboboxdatabound-controls

Accessing ComboBox.Items with Contains method for DataBound ComboBox


Summary:

I want to check the current ComboBox.text value against the list of items in a ComboBox that is assigned a DataSource at run time. If the text doesn't match an item in the list then it will select the first item in the list.


Here is what I originally tried:

' This Load function is just here to give an example of how I bound the ComboBox '
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
    Me.myComboBox.DisplayMember = "something"
    Me.myComboBox.ValueMember = "otherthing"
    Me.myComboBox.DataSource = Me.myDataTable
End Sub

' This function is copy/pasted directly out of my code '
Private Sub myComboBox_Validating(sender As Object, e As System.ComponentModel.CancelEventArgs) Handles myComboBox.Validating
    If Not DirectCast(sender, ComboBox).Items.Contains(DirectCast(sender, ComboBox).Text) Then
        DirectCast(sender, ComboBox).SelectedValue = -1
    End If
End Sub

However the above code does not work as expected because when inspecting the myComboBox.Items property at run time, it is actually a collection of System.Data.DataRowView objects. So basically it is comparing a String to DataRowView.ToString() which is always false unless the myComboBox.Text value is in fact "System.Data.DataRowView"...


So I thought

"Hey, lets make an extension method to search all the items of the DataViewRow and see if my requested value is in there!", but it's not going as planned...

<Extension()>  
Private Function Contains_databound(ByVal items As ComboBox.ObjectCollection, ByVal value As Object) As Boolean
    Dim Success As Boolean = False

    For Each itm In items
        Dim item As DataRowView = Nothing

        Try
            item = DirectCast(itm, DataRowView)
        Catch ex As Exception
            Throw New Exception("Attempted to use a Contains_databound method on a non databound object", New Exception(ex.Message))
        End Try

        If Not IsNothing(item) Then
            For Each rowItem In item.Row.ItemArray
                Dim v1 As String = TryCast(rowItem, String)
                Dim v2 As String = TryCast(value, String)

                If Not IsNothing(v1) And Not IsNothing(v2) Then
                    If v1.Equals(v2) Then
                        Success = True
                    End If
                End If
            Next
        End If
    Next
    Return Success
End Function

I know that looks weird, but the code prettify won't work right if the <Extension()> part isn't separated. When I attempt to use my extension method in my main code, I get an error about my extension method not being a member of ComboBox.ObjectCollection which seems bogus to me because in the extension method I am specifically saying that the first parameter is a ComboBox.ObjectCollection.

Private Sub myComboBox_Validating(sender As Object, e As System.ComponentModel.CancelEventArgs) Handles myComboBox.Validating
    If DirectCast(sender, ComboBox).Items.Contains_databound(DirectCast(sender, ComboBox).Text) Then
        DirectCast(sender, ComboBox).SelectedValue = -1
    End If
End Sub

Infamous "HOW TO BRAIN SURGERY WITH POTATO" request...

How can I determine that the text a user inputs into a databound ComboBox is in the list of items from the DataSource?

Side note: C# answers are fine so long as they have a VB.NET counterpart


Solution

  • What you're actually trying to determine is whether the displayed text of any item matches some other value. To get the displayed text of an item you call GetItemText. I'll post an example.

    Here's an extension method that will do the job:

    Imports System.Runtime.CompilerServices
    
    Public Module ComboBoxExtensions
    
        <Extension>
        Public Function ContainsItemText(source As ComboBox, itemText As String) As Boolean
            Return source.Items.Cast(Of Object).Any(Function(item) source.GetItemText(item) = itemText)
        End Function
    
    End Module