在ComboBox DropDown事件处理程序中设置SelectedIndex

时间:2010-07-01 16:00:55

标签: c# winforms combobox

最近我在Windows 7上重现了此消息的奇怪行为。可能是它的功能,可能不依赖于Windows 7,如果是正确的行为,请纠正我。 在MSDN中我们看到

  

应用程序发送CB_SETCURSEL   用于选择列表中的字符串的消息   一个组合框。如有必要,列表   将字符串滚动到视图中。文本   在组合框的编辑控件中   更改以反映新选择,   以及列表中的任何先前选择   被删除了。

下面的代码段描述了热重现行为:

private void ReproduceBehaviour()
{
    ComboBox comboBox = new ComboBox();
    Controls.Add(comboBox);
    comboBox.DataSource = new List<string> { "A", "b", "B", "C" };
    comboBox.DropDown += new EventHandler((o, e) => { comboBox.SelectedIndex = 2; });
}

因此,当我们在下拉列表中设置SelectedIndex = 2时,应选择项目“B”。但对我来说很奇怪,项目“b”(索引= 1)会被选中! 我们可以直接发送CB_SETCURCELL消息,没有改变:

[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, Int32 wParam, Int32 lParam);
private void ReproduceBehaviour()
{
    ComboBox comboBox = new ComboBox();
    Controls.Add(comboBox);
    comboBox.DataSource = new List<string> { "A", "b", "B", "C" };
    comboBox.DropDown += new EventHandler((o, e) => { SendMessage(comboBox.Handle, 0x14e, 2, 0); });
}

这个功能(?!o_O)或我做错了什么? 谢谢你的回复。

UPD。 据我所知,我试图在下拉事件处理程序上手动将选择设置为列表框。没效果:(

private void ReproduceBehaviour()
{

    ComboBox comboBox = new ComboBox();
    Controls.Add(comboBox);
    comboBox.DataSource = new List<string> { "A", "b", "B", "C" };
    comboBox.DropDown += new EventHandler((o, e) =>
    {
        SendMessage(comboBox.Handle, 0x14e, 2, 0); // CB_SETCURSEL
        ComboBoxInfo pcbi = new ComboBoxInfo();
        pcbi.cbSize = Marshal.SizeOf(pcbi);
        GetComboBoxInfo(comboBox.Handle, ref pcbi);
        IntPtr result = SendMessage(pcbi.hwndList, 0x0186, 2, 0); // LB_SETCURSEL
    });
}

我必须使用LB_SETCURSEL,因为LB_SETSEL返回LB_ERR(LB_SELSET仅适用于多选列表框,但在ComboBox中使用单选列表框)。 方法调用

IntPtr result = SendMessage(pcbi.hwndList, 0x0186, 2, 0); // LB_SETCURSEL

返回值'2',因此我假设选择已成功设置。但是当完全打开下拉列表时,它会像往常一样选择不正确的值:( 可能DropDown事件不是一个正确的地方吗?我很困惑。

1 个答案:

答案 0 :(得分:2)

它不像你想象的那样工作。通过分配SelectedIndex属性,您不选择下拉列表项,您在组合框的文本框部分中设置文本。下拉列表通过选择与文本框文本匹配的列表项来响应。问题是:它以不区分大小写的方式这样做。

通过将第2项设置为“D”,您可以轻松地看到这一点。这解决了它。或者将第一项设置为“b”,现在第一项被选中。

不,没有简单的解决办法。困难的是使用CB_GETCOMBOBOXINFO获取下拉事件中列表框控件的句柄,然后向其发送LB_SETSEL消息。务实的解决方法是不使列表项仅因情况而异。无论如何都倾向于混淆用户。