使用键盘选择列表框项

时间:2012-10-17 08:20:05

标签: c#

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

  • 两个
  • 一旦

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

3 个答案:

答案 0 :(得分: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;
}

希望这有帮助! ;)

<强> EDIT2:

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

答案 1 :(得分:3)

您想使用LBS_SORT list box style。创建控件后无法应用此样式,因此要添加此样式,您需要覆盖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;
        }
    }
}

此列表框现在应该对列表中的项目进行排序。支持增量搜索(你不能关闭排序我害怕,如果你需要控制排序顺序,那么你需要自己进行增量搜索,如阿巴斯建议的那样)

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

答案 2 :(得分: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
    }