質問: ### 前提・実現したいこと WindowsフォームアプリケーションのListBoxに以下のようなデータがある状態で、 キーボードで「123」と入力した時に「123 いいい」のデータを選択したいです。 ![ListBox Items](https://teratail.storage.googleapis.com/uploads/contributed_images/0d1b4150dccd1d286f266dd8ad35b1e4.png) ### 発生している問題・エラーメッセージ 「123」と入力すると最初の一文字でしか選択ができず、「111」「222」「333」の順でデータ 選択されてしまう。 ### 該当のソースコード コード自体はありません。デザイナでフォームにListBoxを置き、 プロパティからデータを追加しました。 ### 試したこと MSDNのページ.aspx)から、該当するプロパティ等が無いかを探しましたが、見当たりませんでした。 Key関連のイベントを駆使して、コードで実装しないと実現不可能なのでしょうか。
回答: 標準の機能としてはありません。 おそらく挙動が曖昧になるためだと思われます。 どういうことかというと、たとえば「123 aa」と「234 bb」の項目があって、 1, 2, 3 の順でキー押下した場合に、押下するスピードによって * 「123」の入力とみなされ、「123 aa」が選択される * 「1」と「23」の入力とみなされ、「123 aa」が選択された後に「234 bb」が選択される というように動きが変わってしまって使いづらいのでは?ということです。 それを承知の上で実現したいのであれば、おっしゃるとおり Keyイベントから自前で実装することになるかと思います。 一応以下に簡易に作ってみたサンプルを載せておきますが、 個人的な意見としては、キーで選択したいなら、別にTextBoxを配置して そこの入力文字から表示項目をインクリメンタルに絞り込む、とかのほうが 使いやすいのでは?という気もします。 ``` public class KeySelectionListBox : ListBox { //キーの連続入力を待機する時間(ミリ秒) const int KeyPressContinueTimeout_ms = 200; //入力された文字をためておく readonly List pressedChars = new List(); //入力が継続している場合に選択処理をキャンセルするためのもの CancellationTokenSource preTaskTokenSource; protected override void OnKeyPress(KeyPressEventArgs e) { //もともとの先頭文字選択の動きを無効化 e.Handled = true; lock (pressedChars) { pressedChars.Add(e.KeyChar); } //入力が継続しているので、確定待機中であればキャンセルしておく if (preTaskTokenSource != null) { preTaskTokenSource.Cancel(); preTaskTokenSource = null; } var tokenSource = new CancellationTokenSource(); preTaskTokenSource = tokenSource; Task.Delay(KeyPressContinueTimeout_ms, tokenSource.Token).ContinueWith(t => { if (t.IsCanceled) return; string input; lock (pressedChars) { input = new string(pressedChars.ToArray()); pressedChars.Clear(); } //先頭から一致する項目があれば選択 var item = this.Items .Cast() .FirstOrDefault(i => i.ToString().StartsWith(input)); if (item != null) this.SelectedItem = item; }, TaskScheduler.FromCurrentSynchronizationContext()); } } ```