加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

.NET WinForms ComboBox,相同的项目和SelectedIndexChanged事件

发布时间:2020-12-17 00:07:08 所属栏目:大数据 来源:网络整理
导读:看起来当你有一个WinForms .NET应用程序和一个ComboBox(设置为“DropDown”样式),并且ComboBox中有多个相同的项目时,会发生奇怪的事情.具体而言,所选项的索引可以更改而不触发SelectedIndexChanged事件. 当然,这会引起大规模的混乱和奇怪的,模糊的错误,这就
看起来当你有一个WinForms .NET应用程序和一个ComboBox(设置为“DropDown”样式),并且ComboBox中有多个相同的项目时,会发生奇怪的事情.具体而言,所选项的索引可以更改而不触发SelectedIndexChanged事件.

当然,这会引起大规模的混乱和奇怪的,模糊的错误,这就是我最近一直把头发拉出来的原因.

这是一个简单的例子,你可以用来看看我在说什么:

>创建一个新的.NET WinForms项目(我使用VB.NET,但随意翻译 – 它很简单).
>将一个ComboBox,一个按钮和一个TextBox(设置MultiLine = True)拖放到表单上.
>使用以下代码加载具有3个相同项目的ComboBox,并在SelectedIndexChanged事件触发时打印一些状态消息,并查看当前选择的索引(通过按钮):

Private Sub ComboBox1_SelectedIndexChanged(ByVal sender As System.Object,ByVal e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged
        TextBox1.Text = TextBox1.Text & vbNewLine & "ComboBox SelectedIndexChanged event fired." & vbNewLine & _
            "SelectedIndex is: " & ComboBox1.SelectedIndex
    End Sub

    Private Sub Form1_Load(ByVal sender As Object,ByVal e As System.EventArgs) Handles Me.Load
        ComboBox1.Items.Add("John Doe")
        ComboBox1.Items.Add("John Doe")
        ComboBox1.Items.Add("John Doe")

    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object,ByVal e As System.EventArgs) Handles Button1.Click
        TextBox1.Text = TextBox1.Text & vbNewLine & _
        "Button clicked." & vbNewLine & _
        "SelectedIndex is: " & ComboBox1.SelectedIndex
    End Sub

运行项目并从ComboBox中选择一个项目(例如,中间项目).然后,单击ComboBox的下拉箭头,但不要选择任何内容.单击按钮(默认为Button1)并查看其内容.

除非我忘记了,否则你应该看到以下内容:

ComboBox SelectedIndexChanged event fired.
SelectedIndex is: 1
Button clicked.
SelectedIndex is: 0

换句话说,SELECTED INDEX已经改变但没有激活SelectedIndexChanged事件!

仅当ComboBox中的项目相同时才会发生这种情况.如果它们不同,则不会发生这种情况. (如果ComboBox的“DropDown”样式设置为“DropDownList”,也不会发生这种情况.)

我怀疑这可能是.NET框架本身的一个错误,而不是我可以解决的问题,但是如果其他人对这里做什么(或者我可能做错了什么)有任何想法的话,请加入!我无法解释这种行为或解决它(我希望SelectedIndex保持不变,除非,你知道,你实际上通过选择其他东西来改变它!)

.NET Framework实际上并不跟踪组合框的下拉列表中选定的索引;这是由Windows API在内部处理的.因此,.NET依赖于Windows API,当所选索引通过发送到组合框的窗口句柄的通知消息发生更改时通知它,以便它可以依次触发SelectedIndexChanged事件.

不幸的是,事实证明,.NET监视的特定通知消息(准确地说是CBN_SELCHANGE)并未涵盖所选索引可能发生变化的所有可能情况.具体来说,如果用户单击或使用箭头键选择下拉列表中的项目,则CBN_SELCHANGE仅由Windows API发送.但是,在DropDown样式组合框中,打开组合框的操作会导致Windows查看组合框的编辑部分中的文本,搜索项目列表以查找匹配项,以及是否找到匹配项选择匹配项(或第一个匹配项,如果有多个匹配项).这可以更改所选索引,但不发送CBN_SELCHANGE通知消息,因此.NET忽略了它已更改的事实,并且不会触发SelectedIndexChanged事件.

Windows在DropDown样式组合框中完成所有这些操作,因为用户无需在下拉列表中选择内容;他们可以打字他们想要什么.因此,每次打开组合框时,它都会假定用户可能已更改了文本,并尝试重新同步列表中的内容(如果可以).

在您的情况下,当您第二次打开组合框时,它将重新同步并选择编辑部分中文本的第一个匹配项,即“John Doe”#0,并将所选索引更改为0 .NET意识到了.

所以它基本上是.NET Framework中的一个错误.遗憾的是,没有完美的解决方法 – 您无法让Windows不进行重新同步,并且在重新同步发生后没有事件会立即触发,您可以在其中获取新选择的索引. (DropDown事件实际上在重新同步发生之前就会触发,因此它不会看到新的索引.)关于你可以做的最好的事情是处理DropDownClosed事件,假设索引可能在那时发生了变化,并采取相应的行动.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读