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.
' 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"...
"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
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
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