gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-04 16:26:45 25 4
gpt4 key购买 nike

似乎当您有一个 WinForms .NET 应用程序和一个 ComboBox(设置为“DropDown”样式),并且该 ComboBox 中有多个相同的项目时,就会发生奇怪的事情。具体来说,可以在不触发 SelectedIndexChanged 事件的情况下更改所选项目的索引。

当然,这会导致大量的困惑和奇怪的、晦涩的错误,这就是我最近一直在纠结的问题。

这是一个简单的示例,您可以使用它来了解我在说什么:

  • 创建一个新的 .NET WinForms 项目(我使用 VB.NET,但可以随意翻译 - 这很简单)。
  • 将组合框、按钮和文本框(设置 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)并查看它的内容。

    除非我失去理智,否则您应该看到以下内容:

    组合框 SelectedIndexChanged 事件已触发。
    SelectedIndex 为:1
    按钮被点击。
    SelectedIndex 为: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 事件,假设索引可能在那个时候发生了变化,并采取相应的行动.

    关于.NET WinForms ComboBox、相同的项目和 SelectedIndexChanged 事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/354408/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com