I'm having some issues with WinForms ComboBox class. What I am trying to achieve is programmatically setting SelectedValue from the ComboBox.TextChanged handler once a match is found. This works fine on Windows 7, but in Windows XP SelectedValue will get set and SelectedValueChanged will be raised, but then once it reaches Validating SelectedValue returns Nothing. It seems the only way to change SelectedValue in XP is via selecting something from the dropdown.

Here's a toy Form with just a ComboBox and a multi-line TextBox.

XP: Typed into the ComboBox is 1Y, then tab is pressed. Output:

SelectedValueChanged: SelectedValue: 1X
Validating: SelectedValue: Nothing
Value is: 
Validated: SelectedValue: Nothing

Win7: Typed into the ComboBox is 1Y, then tab is pressed. Output:

SelectedValueChanged: SelectedValue: 1X
Validating: SelectedValue: 1X
Value is: 1X
Validated: SelectedValue: 1X

Code:

Public Class ComboBoxXPForm
    Private WithEvents mData As New DataHolder
    Private mBindingSrc As BindingSource


    Sub New()

        ' This call is required by the Windows Form Designer.
        InitializeComponent()

        mBindingSrc = New BindingSource() With {.DataSource = mData}

        Dim dt As New DataTable()
        dt.Columns.Add("value", GetType(String))
        dt.Columns.Add("displayValue", GetType(String))

        dt.Rows.Add("", "")
        For i = 1 To 10
            dt.Rows.Add(i & "X", i & "Y")
        Next

        cboBox.DataSource = dt
        cboBox.ValueMember = "value"
        cboBox.DisplayMember = "displayValue"

        cboBox.DataBindings.Add("SelectedValue", mBindingSrc, "StrVal", True)
    End Sub

    Private Sub cboBox_SelectedValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles cboBox.SelectedValueChanged
        txtDebug.Text &= vbNewLine & "SelectedValueChanged: SelectedValue: " & _
            If(cboBox.SelectedValue Is Nothing, _
               "Nothing", cboBox.SelectedValue.ToString())
    End Sub

    Private Sub DataHolder_DebugInfo(ByVal sender As Object, ByVal e As DebugEventArgs) Handles mData.DebugInfo
        txtDebug.Text &= vbNewLine & e.DebugInfo
    End Sub

    Private Sub cboBox_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles cboBox.TextChanged
        'For Each row In cboBox.Items
        '    If cboBox.Text = row("displayValue") AndAlso row("value") <> cboBox.SelectedValue Then
        '        'cboBox.SelectedValue = row("value")
        '        cboBox.SelectedItem = row
        '    End If
        'Next
        For i = 0 To cboBox.Items.Count - 1
            Dim item = cboBox.Items(i)
            If cboBox.Text = item("displayValue") Then
                cboBox.SelectedIndex = i
            End If
        Next
    End Sub

    Private Sub cboBox_Validated(ByVal sender As Object, ByVal e As System.EventArgs) Handles cboBox.Validated
        txtDebug.Text &= vbNewLine & "Validated: SelectedValue: " & _
            If(cboBox.SelectedValue Is Nothing, _
               "Nothing", cboBox.SelectedValue.ToString())
    End Sub

    Private Sub cboBox_Validating(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles cboBox.Validating
        txtDebug.Text &= vbNewLine & "Validating: SelectedValue: " & _
            If(cboBox.SelectedValue Is Nothing, _
               "Nothing", cboBox.SelectedValue.ToString())
    End Sub
End Class

Public Class DebugEventArgs
    Inherits EventArgs

    Private mDebugInfo As String

    Public Sub New(ByVal DebugString As String)
        MyBase.New()
        DebugInfo = DebugString
    End Sub

    Public Property DebugInfo() As String
        Get
            Return mDebugInfo
        End Get
        Set(ByVal value As String)
            mDebugInfo = value
        End Set
    End Property
End Class

Public Class DataHolder
    Public Event DebugInfo(ByVal sender As Object, ByVal e As DebugEventArgs)

    Private mStrVal As String
    Public Property StrVal() As String
        Get
            Return mStrVal
        End Get
        Set(ByVal value As String)
            mStrVal = value
            RaiseEvent DebugInfo(Me, New DebugEventArgs("Value is: " & value))
        End Set
    End Property
End Class
有帮助吗?

解决方案

Try turning AutoCompleteMode to become SuggestAppend, and AutoCompleteSource to become ListItems. Then you can remove the entire TextChanged code block and it should also work properly on XP.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top