C# 使用键盘选择列表框项

C# 使用键盘选择列表框项,c#,C#,有没有人能告诉我,当有多个项目以相同字符开头时,我应该如何通过编程在列表框中使用键盘选择一个项目。 例如 一个 两个 三 一次 橙色的 如果我想通过输入o,n,c来集中注意力在“一次”上,我该怎么做?与默认行为相反,不要从一个项目跳到另一个项目。向列表框添加按键事件处理程序,并跟踪按下的按键。然后将已键入的完整值与列表框中项目的值进行比较。如果存在匹配项,请选择该项 编辑: 这是我创建的一个有效的解决方案。我还测量按键之间的时间。这样,如果到按键之间的时间超过1.5秒,则搜索字符串将清空,并

有没有人能告诉我,当有多个项目以相同字符开头时,我应该如何通过编程在列表框中使用键盘选择一个项目。 例如

  • 一个
  • 两个
  • 一次
  • 橙色的

如果我想通过输入o,n,c来集中注意力在“一次”上,我该怎么做?与默认行为相反,不要从一个项目跳到另一个项目。

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

编辑:

这是我创建的一个有效的解决方案。我还测量按键之间的时间。这样,如果到按键之间的时间超过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
}
private DateTime\u lastKeyPress;
私有字符串_searchString;
私有无效列表框1KeyPress(对象发送者,按键事件参数e)
{
var newDate=DateTime.Now;
var diff=新日期-_lastKeyPress;
如果(差异总秒数>=1.5)
_searchString=string.Empty;
_searchString+=e.KeyChar;
对于(变量i=0;i
下面是一个使用LinQ为searchitem获取匹配项的示例:

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;
}
private void ListBox1KeyPress(对象发送者,按键事件参数e)
{
var newDate=DateTime.Now;
var diff=新日期-_lastKeyPress;
如果(差异总秒数>=1.5)
_searchString=string.Empty;
_searchString+=e.KeyChar;
var found=listBox1.Items.Cast().Select(t=>t.ToString()).Where(item=>item.ToLower().StartsWith(_searchString)).FirstOrDefault();
如果(!String.IsNullOrEmpty(已找到))
listBox1.SelectedItem=found;
_lastKeyPress=newDate;
e、 已处理=正确;
}
希望这有帮助!;)

Edit2:


我不知道您是否注意到带有
e.Handled
重要性的注释。默认情况下,如果按下列表框中的某个键,控件将选择第一个找到的具有该键字符的项。但它没有我的代码所具有的功能。因此,如果您遥控
e.Handled
行,代码将工作,但控件也将处理按键,您不希望这样:项目将无法正确选择

您想使用
LBS\u排序
。创建控件后无法应用此样式,因此要添加此样式,需要覆盖该属性。创建一个从
ListBox
派生的类(称之为
SortedListBox
),并像这样重写此属性

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,显示增量搜索当前匹配的字符

我刚刚为我的案例修改了阿巴斯代码。这是我的桌面程序,用在一个有列表框控件的窗体中。这对我来说很有效。感谢阿巴斯

    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
    }

在第一个列表中,您需要“listBox1.SelectedItem=listBox1.Items[i]”,而不是“listBox1.SelectedItem=item”。根据我的测试,上面的注释是错误的。它与“listBox1.SelectedItem=item”一起工作,如答案所示。它不适用于“listBox1.SelectedItem=listBox1.Items[i]”