6

我之前问过一个关于如何在 C# 中选择动态创建的列表框项目的问题,得到了回答。现在的问题是当列表框在弹出时获得焦点!除非我选择一个项目或按 Esc,否则我无法继续输入,我已明确定义将焦点设置回我的TextBox.

具有讽刺意味的是,我的KeyDown事件中有一个条件,即如果按下向上或向下箭头键,则将焦点设置在ListBox以便用户可以选择一个项目,但不要转移焦点以便用户可以继续自由输入。

就像我们在 Visual Studio 上的一样,当用户按下一个点时,他不会被阻止并被迫从 Intellisense 列表中选择一个项目,但他可以继续输入或随时使用向上向下箭头键来选择适当的项目。

我无法使用下面的代码实现相同的功能。我怎样才能让它像提到的那样工作?

我需要说的是,使用 ActiveControl 和 transferFocus,使用this.Focus()之前lst.Focus(),禁用和启用文本框都不起作用!

private void txtResults_KeyDown(object sender, KeyEventArgs e)
{
   string[] words= ((TextBox)sender).Text.Split(' ');
   string s = sampleWord.Text = words[words.Length - 1];

    if (e.KeyCode == Keys.OemPeriod)
    {
        ShowPopUpList(s);
        lst.Focus();     //This transfers the focus to listbox but then prevents user
                         //from being able to type anymore unless he/she chooses an item!
    }
    else if (e.KeyCode == Keys.Down || e.KeyCode == Keys.Up)
    {
        lst.Focus();//doesnt work :-/
    }
    else
    {
        lst.Hide();
        txtResults.Focus();
    }
}
4

3 回答 3

3

发生此行为是因为您将焦点转移到列表框。尝试以不同的方式思考它,而不是将焦点放在列表框上,而是在按下向上或向下箭头时选择列表中的下一个/上一个项目。

将您的“else if”更改为以下内容:

        else if (e.KeyCode == Keys.Down)
        {
            if (lst.SelectedIndex + 1 < lst.Items.Count)
            {
                lst.SelectedIndex += 1; 
            }
            e.Handled = true;
        }
        else if (e.KeyCode == Keys.Up)
        {
            if (lst.SelectedIndex - 1 >= 0)
            {
                lst.SelectedIndex -= 1;
            }
            e.Handled = true;
        }
于 2013-08-02T22:42:05.647 回答
2

如果您希望用户能够在仍然操作列表框的选择的同时继续在文本框中输入内容,那么您将不得不伪造它:在显示列表框时不要实际将焦点设置到列表框。相反,在文本框的KeyDown事件中手动更改列表框的选择。像这样的东西:

private void txtResults_KeyDown(object sender, KeyEventArgs e)
{
    string[] words = ((TextBox)sender).Text.Split(' ');
    string s = sampleWord.Text = words[words.Length - 1];

    if (e.KeyCode == Keys.OemPeriod)
    {
        ShowPopUpList(s);
        lst.SelectedIndex = 0;
    }
    else if (lst.Visible && e.KeyCode == Keys.Up)
    {
        // manipulate the selection on the listbox (move up)
        if (lst.SelectedIndex > 0) 
            lst.SelectedIndex -= 1;

        // eat the keypress so it textbox doesn't get it and move the cursor
        e.Handled = true; 
    }
    else if (lst.Visible && e.KeyCode == Keys.Down)
    {
        // manipulate the selection on the listbox (move down)
        if (lst.SelectedIndex < lst.Items.Count - 1) 
            lst.SelectedIndex += 1;

        // eat the keypress so it textbox doesn't get it and move the cursor
        e.Handled = true;
    }
    else if (lst.Visible && e.KeyCode == Keys.Enter)
    {
        // insert current list box selection into text box and hide the list
        txtResults.Text += lst.SelectedItem;
        txtResults.SelectionStart = txtResults.Text.Length;
        lst.Hide();
        // eat the keypress to prevent the textbox (and the form) from acting on it
        e.SuppressKeyPress = true;
        e.Handled = true;
    }
    else
    {
        lst.Hide();
    }
}
于 2013-08-02T22:33:10.833 回答
2

您不需要专注ListBox于让您的用户使用它来选择它的项目Arrow keysTextBox应该始终保持专注,您必须在您的事件处理程序中处理Enter权利,在KeyDown您的事件处理程序中添加TextBox所选项目,像这样的东西:KeyDownListBox

private void txtResults_KeyDown(object sender, KeyEventArgs e)
{
  string[] words= ((TextBox)sender).Text.Split(' ');
  string s = sampleWord.Text = words[words.Length - 1];

  if (e.KeyCode == Keys.OemPeriod)
  {
    ShowPopUpList(s);//Show your ListBox without needing to focus it.        
  }

  if(lst.Visible){
    if(e.KeyCode == Keys.Down){      
      lst.SelectedIndex = (lst.SelectedIndex + 1) % lst.Items.Count;
    }
    else if (e.KeyCode == Keys.Up){
      lst.SelectedIndex = lst.SelectedIndex == 0 ? lst.Items.Count - 1 : lst.SelectedIndex - 1
    }
    else if (e.KeyCode == Keys.Enter){//Add the selected Item
        //Add the selected Item here not in the KeyDown event handler of your ListBox
        //.........
        //.........
        //Your TextBox may not need to handle the Enter, so just suppress it after adding the selected item
        e.Handled = true;
    }
    else
    {
      lst.Hide();
    }
  }
}
于 2013-08-03T02:51:31.890 回答