C# にコンボボックスがあり、オートコンプリートの提案を使用したいのですが、有効なエントリが多すぎてAutoCompleteStringCollection
起動時に入力できないため、ユーザーの入力に応じてオートコンプリートのエントリを変更できるようにしたいと考えています。
例として、ユーザーに名前を入力させているとします。可能な名のリスト ("Joe"、"John") と姓のリスト ("Bloggs"、"Smith") がありますが、それぞれが 1000 個ある場合、可能な文字列は 100 万個になりますオートコンプリート エントリに入れるには多すぎます。したがって、最初は最初の名前だけを提案として ("Joe", "John") たいと思います。次に、ユーザーが最初の名前 ("Joe") を入力したら、既存のオートコンプリート エントリを削除して置き換えます。選択された名前とそれに続く可能な姓 ("Joe Bloggs"、"Joe Smith") で構成される新しいセットを使用してそれらを作成します。これを行うために、次のコードを試しました。
void InitializeComboBox()
{
ComboName.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
ComboName.AutoCompleteSource = AutoCompleteSource.CustomSource;
ComboName.AutoCompleteCustomSource = new AutoCompleteStringCollection();
ComboName.TextChanged += new EventHandler( ComboName_TextChanged );
}
void ComboName_TextChanged( object sender, EventArgs e )
{
string text = this.ComboName.Text;
string[] suggestions = GetNameSuggestions( text );
this.ComboQuery.AutoCompleteCustomSource.Clear();
this.ComboQuery.AutoCompleteCustomSource.AddRange( suggestions );
}
ただし、これは正しく機能しません。Clear() を呼び出すと、コンボ ボックスに次の文字が表示されるまでオート コンプリート メカニズムが「オフ」になるようですが、もちろん、次の文字が表示されると、上記のコードは Clear() を再度呼び出すため、ユーザーは決して実際にオートコンプリート機能が表示されます。また、コンボ ボックスの内容全体が選択されるため、キーを押すたびに既存のテキストを選択解除する必要があり、使用できなくなります。Clear() の呼び出しを削除すると、オートコンプリートは機能しAddRange()
ますが、追加した新しい提案がオートコンプリートのドロップダウンに表示されないため、呼び出しは効果がないようです。
これに対する解決策を探していて、さまざまな提案がありましたが、どれも機能しません。オートコンプリート機能が無効になっているように見えるか、新しい文字列が表示されません。ここに私が試したことのリストがあります:
BeginUpdate()
弦交換前と交換後の呼び出しEndUpdate()
。Remove()
Clear() の代わりにすべての既存の文字列を呼び出します。- 文字列の更新中にコンボボックスからテキストをクリアし、後で追加し直します。
- 文字列を変更している間は「なし」に設定
AutoCompleteMode
し、後で「SuggestAppend」に戻します。 TextUpdate
の代わりにまたはKeyPress
イベントをフックしTextChanged
ます。- 毎回
AutoCompleteCustomSource
新しいものと既存のものを交換します。AutoCompleteStringCollection
さまざまな組み合わせであっても、これらのどれも役に立ちませんでした。 SpenceComboBox
は、オートコンプリートで使用する文字列のリストを取得する関数をオーバーライドしてみることを提案しました。リフレクターを使用して、ComboBox
有望に見えるクラスGetStringsForAutoComplete()
内のいくつかのメソッドを見つけましたSetAutoComplete()
が、それらは両方ともプライベートであるため、派生クラスからアクセスできません。私はそれ以上取ることができませんでした。
ComboBox
オートコンプリート インターフェースは同じなので、をに置き換えてTextBox
みましたが、動作が少し異なることがわかりました。を使用するTextBox
と、オートコンプリートの追加部分が適切に機能するように見えますが、提案部分は機能しません。提案ボックスは一時的に点滅しますが、すぐに消えます。
そこで、「さて、サジェスト機能なしで生きて、代わりに追加を使用する」と思ったのですが、AutoCompleteMode
追加に設定すると、アクセス違反の例外が発生します。SuggestAppend
サジェストでも同じことが起こります。サジェスト部分が正しく動作しなくても、例外をスローしない唯一のモードはです。
C# マネージ コードを使用する場合、アクセス違反の例外を取得することは不可能であると考えられていました。 Avramは、これを修正するために「ロック」を使用することを提案しましたが、何をロックすればよいかわかりAutoCompleteStringCollection
ません。ComboBox
またはもロックしようとしましTextBox
たが、どちらも役に立ちませんでした。私が理解しているように、ロックは他のロックを防ぐだけなので、基になるコードがロックを使用していない場合、ロックを使用しても違いはありません。
このすべての結果は、現在、ダイナミックオートコンプリートでaTextBox
または aを使用できないことです。ComboBox
どうすればこれを達成できるかについての洞察を持っている人はいますか?
アップデート:
私はまだこれを機能させていませんが、さらにいくつか発見しました。たぶん、これのいくつかは、他の誰かが解決策を考え出すきっかけになるでしょう.
ComboBox
オートコンプリート インターフェースは同じなので、をに置き換えてTextBox
みましたが、動作が少し異なることがわかりました。を使用するTextBox
と、オートコンプリートの追加部分が適切に機能するように見えますが、提案部分は機能しません。提案ボックスは一時的に点滅しますが、すぐに消えます。
そこで、「さて、サジェスト機能を使わずに Append を使用することにしよう」と考えましたが、AutoCompleteMode
Append に設定すると、アクセス違反の例外が発生します。SuggestAppend
サジェストでも同じことが起こります。サジェスト部分が正しく動作しなくても、例外をスローしない唯一のモードはです。
C# マネージ コードを使用する場合、アクセス違反の例外を取得することは不可能であると考えられていましたが、いずれにせよ、現在、動的オート コンプリートでaTextBox
または aを使用することはできません。ComboBox
どうすればこれを達成できるかについての洞察を持っている人はいますか?
更新 2:
ワーカー スレッドでオートコンプリートを変更したり、PostMessage() 型の動作をシミュレートするために使用したりするなど、さまざまなことを試した後、BeginInvoke()
最終的にあきらめて、リスト ボックスを使用して独自のオート コンプリート ドロップダウンを実装しました。組み込みのものよりもはるかに応答性が高く、組み込みのものを機能させるために費やした時間よりも少ない時間でした。自分で実装します。