3

谁能告诉我当有多个以相同字符开头的项目时,我应该以编程方式做什么才能使用键盘选择列表框中的项目。例如,

  • 一次
  • 橙子

如果我想通过输入 o,n,c 来关注“Once”,我应该怎么做?而不是从一个项目跳到另一个项目,而不是默认行为。

4

3 回答 3

4

将 KeyPress 事件处理程序添加到 ListBox 并跟踪按下的键。然后将已键入的完整值与 ListBox 中的项目的值进行比较。如果有匹配项,请选择该项目。

编辑:

这是我创建的一个有效的解决方案。我还测量了按键之间的时间。这样,如果两次按键之间的时间超过 1.5 秒,则搜索字符串将被清空并用最后一个搜索字符重新填充。之后就像我说的:找到一个匹配项,如果有匹配项,请选择该项目。这两个私有字段是类级别的字段,用于跟踪最后一次按键的时间,字符串用于存储搜索字符串。

private DateTime _lastKeyPress;
private string _searchString;

private void ListBox1KeyPress(object sender, KeyPressEventArgs e)
{
    var newDate = DateTime.Now;
    var diff = newDate - _lastKeyPress;

    if (diff.TotalSeconds >= 1.5)
        _searchString = string.Empty;
    _searchString += e.KeyChar;

    for (var i = 0; i < listBox1.Items.Count; i++)
    {
        var item = listBox1.Items[i].ToString();
        if (item.ToLower().StartsWith(_searchString))
        {
            listBox1.SelectedItem = item;
            break;
        }
    }
    _lastKeyPress = newDate;
    e.Handled = true; //REALLY IMPORTANT TO HAVE THIS
}

这是一个使用 LinQ 来匹配搜索项的示例:

private void ListBox1KeyPress(object sender, KeyPressEventArgs e)
{
    var newDate = DateTime.Now;
    var diff = newDate - _lastKeyPress;
    if (diff.TotalSeconds >= 1.5)
        _searchString = string.Empty;
    _searchString += e.KeyChar;

    var found = listBox1.Items.Cast<object>().Select(t => t.ToString()).Where(item => item.ToLower().StartsWith(_searchString)).FirstOrDefault();
    if(!String.IsNullOrEmpty(found))
        listBox1.SelectedItem = found;

    _lastKeyPress = newDate;
    e.Handled = true;
}

希望这可以帮助!;)

编辑2:

不知道大家有没有注意到评论的重要性e.Handled。默认情况下,如果您按下 ListBox 中的某个键,控件将选择第一个找到的具有该键字符的项。但它没有我的代码所具有的功能。因此,如果您远程控制e.Handled线路,代码将起作用,但控件也会处理按键,而您不希望这样:项目不会被正确选择!

于 2012-10-17T08:23:16.927 回答
3

您想使用LBS_SORT 列表框样式。创建控件后无法应用此样式,因此要添加此样式,您需要覆盖该CreateParams属性。创建一个SortedListBox派生自ListBox并覆盖此属性的类(让我们调用它),如下所示

public class MyListBox : ListBox
{
    protected override CreateParams CreateParams
    {
        get
        {
            var returnValue = base.CreateParams;
            returnValue.Style |= 0x2; // Add LBS_SORT
            returnValue.Style ^= 128; // Remove LBS_USETABSTOPS (optional)
            return returnValue;
        }
    }
}

这个列表框现在应该对列表中的项目进行排序并支持增量搜索(恐怕你不能关闭排序,如果你需要控制排序顺序,那么你需要自己进行增量搜索,就像 Abbas已建议)

更新:如果您另外删除了LBS_USETABSTOPS样式,您甚至会得到一个编辑框,显示增量搜索当前匹配的字符

于 2012-10-17T13:14:38.337 回答
0

我刚刚为我的案例修改了 Abbas 代码。这是我的桌面程序,并以其中一种具有 ListBox 控件的形式使用。这对我很有用。感谢阿巴斯

    private DateTime _lastKeyPress;
    private string _searchString;
    private void lstEmployer_KeyPress(object sender, KeyPressEventArgs e)
    {
        var newDate = DateTime.Now;
        var diff = newDate - _lastKeyPress;

        if (diff.TotalSeconds >= 2)
            _searchString = string.Empty;
        _searchString += e.KeyChar;

        lstEmployer.SelectedIndex = lstEmployer.FindString(_searchString);

        _lastKeyPress = newDate;
        e.Handled = true; //REALLY IMPORTANT TO HAVE THIS
    }
于 2014-08-13T15:02:27.607 回答