I didn't find any good solution for my issue. A bit of explanations. I have DataGridView with a few Columns. In the first Column, the cell shows the path to some file. Starting from the third Column, I have couple of ComboBoxCells.
In the DropDown of the ComboBoxes, I wish to make auto-select equal (case insensitive) values to the part of the File path in the first cell. All this happens on Form.Load
.
Later, users make their own choices.
Dim CmbCell As DataGridViewComboBoxCell = CType(DgvRow.Cells(2), DataGridViewComboBoxCell)
Dim ResultString As String
If HasDropDownThisValue(DgvRow.Cells(0).Value.ToString, CmbCell, ResultString) Then
CmbCell.Value = CmbCell.Items(CmbCell.Items.IndexOf(ResultString))
End If
This is the method used in the If
statement:
Private Function HasDropDownThisValue(ByVal GivenValue As String, ByRef comboCeel As DataGridViewComboBoxCell, ByRef ReturnValue As String) As Boolean
ReturnValue = ""
Dim boolret As Boolean = False
Dim comparestring As String
Dim StringArr() As String = Split(GivenValue, CStr(Path.DirectorySeparatorChar), -1, VisualBasic.CompareMethod.Text)
comparestring = StringArr(0)
For i As Integer = 1 To UBound(StringArr)
If comboCeel.Items.Cast(Of String).Contains(comparestring, StringComparer.OrdinalIgnoreCase) Then
ReturnValue = comparestring
boolret = True
Exit For
Else
comparestring = String.Format("{0}{1}{2}", comparestring, Path.DirectorySeparatorChar, StringArr(i))
End If
Next
Return boolret
End Function
The line:
CmbCell.Value = CmbCell.Items(CmbCell.Items.IndexOf(ResultString))
throws an exception when the case doesn't match. How to avoid that?
I probably can do something like: CmbCell.Value = ResultString
, but I prefer to pre-define values in Items collection.
Maybe something like this is possible (used in a function):
comboCeel.Items.Cast(Of String).Contains(comparestring, StringComparer.OrdinalIgnoreCase)
Since you need a case-insensitive match, you can use IndexOf(), with the StringComparison option set to StringComparison.OrdinalIgnoreCase
, to find a string value in the DataGridViewComboBoxCell.ObjectCollection
(which represents a collection of strings, in this case).
I suggest to set Dim ResultString As String = Nothing
and not to reset it to String.Empty
(""
) in the HasDropDownThisValue
method: if the method returns False
, you then set [ComboBoxCell].Value = ResultString
(which is Nothing
), so the ComboBox selection is cleared.
Otherwise, use IndexOf()
to find a matching string in the collection. Still, if no match is found, the resulting value will be Nothing
, so the ComboBox is cleared; otherwise set the value found:
(local variables renamed to comply with standard naming conventions)
Dim resultString As String = Nothing
Dim cmbCell = CType(DgvRow.Cells(2), DataGridViewComboBoxCell)
If HasDropDownThisValue(DgvRow.Cells(0).Value?.ToString(), cmbCell, resultString) Then
resultString = cmbCell.Items.OfType(Of String).
FirstOrDefault(Function(i) i.IndexOf(resultString, StringComparison.OrdinalIgnoreCase) >= 0)
End If
cmbCell.Value = resultString
As you can see, passing resultString
as reference becomes quite useless. You can change your method to return a String instead of a Boolean, since we need to use that string anyway (no matter whether HasDropDownThisValue
finds a match or not).
Also, you shouldn't pass the ComboBox Cell ByRef
: this object is already a Reference Type, you should pass it ByVal
(or don't specify the modifier, since ByVal
is the default).