web-dev-qa-db-ja.com

WinFormsデスクトップアプリケーションでオートコンプリートテキストボックスを作成する方法

単語のリストがあります。リストには約100〜200のテキスト文字列が含まれています(実際には地下鉄の駅の名前です)。

オートコンプリートテキストボックスを作成したい。たとえば、ユーザーが「N」の文字を押すと、適切なオプション(の終わり)が表示されます(1つのオプションのみ)。エンディングを選択する必要があります。

どうやってするか?

PS1:おそらく、次のようなプロパティを持つテキストボックスコントロールがあります。

List<string> AppropriateOptions{/* ... */}

PS2:私の英語でごめんなさい。あなたが理解していなかったなら->私に聞いてください、そして私は説明しようとします!

16
alex4

@lenielのリンクがダウンした場合に備えて、トリックを実行するコードを次に示します。

AutoCompleteStringCollection allowedTypes = new AutoCompleteStringCollection();
allowedTypes.AddRange(yourArrayOfSuggestions);
txtType.AutoCompleteCustomSource = allowedTypes;
txtType.AutoCompleteMode = AutoCompleteMode.Suggest;
txtType.AutoCompleteSource = AutoCompleteSource.CustomSource;
23
Joel

TextBoxの代わりにComboBoxを使用してください。次の例はオートコンプリートし、開始文字だけでなく、テキストの任意の部分に一致します。

これは完全なフォームである必要があります。独自のデータソースとデータソースの列名を追加するだけです。 :-)

using System;
using System.Data;
using System.Windows.Forms;

public partial class frmTestAutocomplete : Form
{

    private DataTable maoCompleteList;
    private const string MC_DISPLAY_COL = "name";
    private const string MC_ID_COL = "id";

    public frmTestAutocomplete()
    {
        InitializeComponent();
    }

    private void frmTestAutocomplete_Load(object sender, EventArgs e)
    {

        maoCompleteList = oData.PurificationRuns;
        maoCompleteList.CaseSensitive = false; //turn off case sensitivity for searching

        testCombo.DisplayMember = MC_DISPLAY_COL;
        testCombo.ValueMember = MC_ID_COL;
        testCombo.DataSource = GetDataTableFromDatabase();
        testCombo.SelectedIndexChanged += testCombo_SelectedIndexChanged;
        testCombo.KeyUp += testCombo_KeyUp;
    }


    private void testCombo_KeyUp(object sender, KeyEventArgs e)
    {
        //use keyUp event, as text changed traps too many other evengts.

        ComboBox oBox = (ComboBox)sender;
        string sBoxText = oBox.Text;

        DataRow[] oFilteredRows = maoCompleteList.Select(MC_DISPLAY_COL + " Like '%" + sBoxText + "%'");

        DataTable oFilteredDT = oFilteredRows.Length > 0
                                ? oFilteredRows.CopyToDataTable()
                                : maoCompleteList;

        //NOW THAT WE HAVE OUR FILTERED LIST, WE NEED TO RE-BIND IT WIHOUT CHANGING THE TEXT IN THE ComboBox.

        //1).UNREGISTER THE SELECTED EVENT BEFORE RE-BINDING, b/c IT TRIGGERS ON BIND.
        testCombo.SelectedIndexChanged -= testCombo_SelectedIndexChanged; //don't select on typing.
        oBox.DataSource = oFilteredDT; //2).rebind to filtered list.
        testCombo.SelectedIndexChanged += testCombo_SelectedIndexChanged;


        //3).show the user the new filtered list.
        oBox.DroppedDown = true; //this will overwrite the text in the ComboBox, so 4&5 put it back.

        //4).binding data source erases text, so now we need to put the user's text back,
        oBox.Text = sBoxText;
        oBox.SelectionStart = sBoxText.Length; //5). need to put the user's cursor back where it was.


    }

    private void testCombo_SelectedIndexChanged(object sender, EventArgs e)
    {

        ComboBox oBox = (ComboBox)sender;

        if (oBox.SelectedValue != null)
        {
            MessageBox.Show(string.Format(@"Item #{0} was selected.", oBox.SelectedValue));
        }
    }

}

//=====================================================================================================
//      code from frmTestAutocomplete.Designer.cs
//=====================================================================================================
partial class frmTestAutocomplete

{
    /// <summary>
    /// Required designer variable.
    /// </summary>
    private readonly System.ComponentModel.IContainer components = null;

    /// <summary>
    /// Clean up any resources being used.
    /// </summary>
    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }

    #region Windows Form Designer generated code

    /// <summary>
    /// Required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    {
        this.testCombo = new System.Windows.Forms.ComboBox();
        this.SuspendLayout();
        // 
        // testCombo
        // 
        this.testCombo.FormattingEnabled = true;
        this.testCombo.Location = new System.Drawing.Point(27, 51);
        this.testCombo.Name = "testCombo";
        this.testCombo.Size = new System.Drawing.Size(224, 21);
        this.testCombo.TabIndex = 0;
        // 
        // frmTestAutocomplete
        // 
        this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
        this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
        this.ClientSize = new System.Drawing.Size(292, 273);
        this.Controls.Add(this.testCombo);
        this.Name = "frmTestAutocomplete";
        this.Text = "frmTestAutocomplete";
        this.Load += new System.EventHandler(this.frmTestAutocomplete_Load);
        this.ResumeLayout(false);

    }

    #endregion

    private System.Windows.Forms.ComboBox testCombo;
}
2
mike

Lenielによる回答リンクはvb.netにありました、Joelにエントリをありがとう。より明確にするためにコードを提供する:

private void InitializeTextBox()
{

    AutoCompleteStringCollection allowedStatorTypes = new AutoCompleteStringCollection();
    var allstatortypes = StatorTypeDAL.LoadList<List<StatorType>>().OrderBy(x => x.Name).Select(x => x.Name).Distinct().ToList();

    if (allstatortypes != null && allstatortypes.Count > 0)
    {
        foreach (string item in allstatortypes)
        {
            allowedStatorTypes.Add(item);
        }
    }

    txtStatorTypes.AutoCompleteMode = AutoCompleteMode.Suggest;
    txtStatorTypes.AutoCompleteSource = AutoCompleteSource.CustomSource;
    txtStatorTypes.AutoCompleteCustomSource = allowedStatorTypes;
}
1
David

TextBoxの標準のオートコンプリートは文字列の最初からしか機能しないため、Nを押すと、Nで始まる文字列のみが検出されることを付け加えたいと思います。より良いものが必要な場合は、別のコントロールを使用するか、自分で動作を実装する必要があります(つまり、IndexOf(inputString)でトークンリスト検索をフィルタリングしてから、AutoCompleteSourceをに設定するよりも、タイマーを使用してTextChangedイベントに反応して実行を遅らせる必要があります。フィルタリングされたリスト。

0
SomeCoder

TextBox.AutoCompleteSourceCustomSourceに設定してから、すべての文字列をAutoCompleteCustomSourceプロパティ(StringCollection)に追加します。その後、あなたは行ってもいいはずです。

0
Dan Tao

コンボボックスを使用するか、データソースを設定するか、ハードコードされたエントリを指定しますが、次のプロパティを設定します。

    AutoCompleteMode = Suggest;
    AutoCompleteSource = ListItems;
0
Abdul Rauf