可以';不要关注C#中动态创建的列表框

本文关键字:动态 创建 列表 可以 | 更新日期: 2023-09-27 18:26:14

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

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

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

使用下面的代码我无法实现相同的功能。如前所述,我如何使其发挥作用?

我需要说的是,使用ActiveControl和transferFocus,在lst.Focus()之前使用this.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();
    }
}

可以';不要关注C#中动态创建的列表框

发生这种行为是因为您正在将焦点转移到列表框。试着用不同的方式思考,不要把重点放在列表框上,而是在按下向上或向下箭头时选择列表中的下一个/上一个项目。

将您的"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;
        }

如果您希望用户能够在操作列表框的选择的同时继续在文本框中键入,那么您必须伪造它:当您显示列表框时,不要实际将焦点设置为列表框。相反,请在文本框的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();
    }
}

您不需要集中ListBox以允许用户使用Arrow keys选择其项目,您的TextBox应该始终集中,您必须在TextBoxKeyDown事件处理程序中处理Enter,将所选项目添加到ListBoxKeyDown事件处理程序之外的位置,类似于以下内容:

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();
    }
  }
}