14

Easy one for you guys.

I have a textbox on top of a listbox.

The textbox is use to filter ther data in the listbox.

So... When the user type in the textbox, I would like to "trap" the down/up/pagedown/pageup keystrokes and fowarding them to the listbox.

I know I could use the Win32 API and send the WM_KeyDown message. But there's must be some .NET way to do this.

Welbog
  • 59,154
  • 9
  • 110
  • 123
vIceBerg
  • 4,197
  • 5
  • 40
  • 53
  • Selected best answer it not the best solution in all situations ! See SendMessage() answer below. – schlebe May 05 '20 at 20:09

5 Answers5

16

SendKeys.Send() Method.

 private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
        {
            listBox1.Focus();
            SendKeys.Send(e.KeyChar.ToString());
        }

Here is code through which you can select a list item.

private void Form1_Load(object sender, EventArgs e)
        {
            textBox1.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
            textBox1.AutoCompleteSource=AutoCompleteSource.CustomSource;
            string[] ar = (string[])(listBox1.Items.Cast<string>()).ToArray<string>();
            textBox1.AutoCompleteCustomSource.AddRange(ar);
        }
        private void textBox1_TextChanged(object sender, EventArgs e)
        {
            listBox1.Text  = textBox1.Text;
        }
KV Prajapati
  • 93,659
  • 19
  • 148
  • 186
  • 4
    How do I tell SendKeys.Send to send the keystroke to the listbox control? – vIceBerg Aug 12 '09 at 04:40
  • 2
    And if I want the focus to stay in the textbox, I do textbox.focus() right after? Weird that sendkey don't have an overload to pass a control to it... – vIceBerg Aug 12 '09 at 04:53
2
    private void textBox_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
    {
        if (e.KeyCode == Keys.PageUp || e.KeyCode == Keys.PageDown || e.KeyCode == Keys.Up || e.KeyCode == Keys.Down)
        {
            // Setting e.IsInputKey to true will allow the KeyDown event to trigger.
            // See "Remarks" at https://msdn.microsoft.com/en-us/library/system.windows.forms.control.previewkeydown(v=vs.110).aspx
            e.IsInputKey = true;
        }
    }

    private void textBox_KeyDown(object sender, KeyEventArgs e)
    {
        string send = "";
        if (e.KeyCode == Keys.PageUp)
        {
            send = "PGUP";
        }
        else if (e.KeyCode == Keys.PageDown)
        {
            send = "PGDN";
        }
        else if (e.KeyCode == Keys.Up)
        {
            send = "UP";
        }
        else if (e.KeyCode == Keys.Down)
        {
            send = "DOWN";
        }
        if (send != "")
        {
            // We must focus the control we want to send keys to and use braces for special keys.
            // For a list of all special keys, see https://msdn.microsoft.com/en-us/library/system.windows.forms.sendkeys.send(v=vs.110).aspx.
            listBox.Focus();
            SendKeys.SendWait("{" + send + "}");
            textBox.Focus();
            // We must mark the key down event as being handled if we don't want the sent navigation keys to apply to this control also.
            e.Handled = true;
        }
    }
Stacey Richards
  • 6,536
  • 7
  • 38
  • 40
1

You can use Data Binding

            listBox1.DataBindings.Add("DataSource", textBox1, "Text", true, DataSourceUpdateMode.OnPropertyChanged).
            Format += (sender, e) =>
            {
                e.Value = _strings.FindAll(s => s.StartsWith((string) e.Value));
            };
Jacob Seleznev
  • 8,013
  • 3
  • 24
  • 34
  • Data binding to send a keystroke to another control?? – vIceBerg Aug 12 '09 at 04:42
  • No, to filter ther data in the list box. If you bind Text property of the textbox to DataSource property of the listbox and use DataSourceUpdateMode.OnPropertyChanged you can achieve this. – Jacob Seleznev Aug 12 '09 at 04:49
  • Oh... I think I can't do this. Because the listbox items are already filled with a List<> binded to the datasource property... – vIceBerg Aug 12 '09 at 05:00
  • You need to somehow filter the listbox content in the Format event for the binding. – Jacob Seleznev Aug 12 '09 at 05:24
0

In our wpf app we have a textbox that filters a listbox, we use the previewkeyup event. Inside the code, we can check what key was pressed (don't have my code in front of me, it's something like e.Key == Key.UpArrow, either way there's a built in class in C# for this). If it's one of the hot keys, we manipulate the user control accordingly.

For the listbox we tossed it into a user control and implemented an interface, called it NavigateableListbox or something like that, forced it to implement MoveUp(), MoveDown(), PageUp(), PageDown() etc so the textbox event just says if e.Key = Key.UpArrow { mylistbox.MoveUp() }

Eric
  • 773
  • 1
  • 5
  • 9
0

SendKeys.Send() method does'nt work in all situations because Send() method can be addressed to another Control !

In 2020, the best solution to be sure at 100% is to use SendMessage() function.

In VB.Net, I use following code

Public Declare Auto Function SendMessage Lib "user32.dll"
    ( ByVal hWnd As IntPtr
    , ByVal wMsg As Int32
    , ByVal wParam As Int32
    , ByVal s As Int32
    ) As Int32

Private Const WM_CHAR As Int32 = &H102

SendMessage(txtInput.Handle, WM_CHAR, AscW(sValue.Chars(0)), 0)

Where txtInput is a sample Textbox control.

In my case, I click on html <div> element defined in a WebView control that changes color when I click on it or when mouse move over. When I click on this <div> a ScriptNotify() VB.Net method is called to enter some characters in Textbox using SendMessage() function.

In old solution, I think that sometimes, WebView gain focus before SendKeys.Send() method is called so that propagated key is not send to txtInput Textbox.

You can use old solution, but be certain that one day, SendKeys.Send() function will send what you want to another Handle.

schlebe
  • 3,387
  • 5
  • 37
  • 50