C#中的自动完成文本框具有奇怪的行为

时间:2012-08-13 14:14:58

标签: c# winforms autocomplete

在C#的Windows.Forms表单中,我有一个组合框和一个文本框。文本框已使用AutoCompleteCustomSource启用了自动完成功能。 AutoCompleteCustomSource中的元素取决于组合框的选定值。这意味着每次组合框的值发生变化时我都必须更改AutoComplete值。但这样做我经历了一些我不喜欢的奇怪行为:

  • 自动完成的文字在离开并重新输入文本框后保持选中状态
  • 离开并重新输入文本框时,即使我点击字符之间的某处,光标也会始终放在文本的末尾
  • 使用退格键会导致建议框出现

我有以下简短的示例代码,其中显示了所描述的行为。 尝试在文本框中输入“必须”。按下键盘上的TAB后,应建议并添加“野马”。现在从组合框中选择“福特”并重新输入文本框以查看我的意思。

Form2.Designer.cs

partial class Form2
{
    /// <summary>
    /// Required designer variable.
    /// </summary>
    private 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.comboBox1 = new System.Windows.Forms.ComboBox();
        this.label1 = new System.Windows.Forms.Label();
        this.label2 = new System.Windows.Forms.Label();
        this.textBox1 = new System.Windows.Forms.TextBox();
        this.textBox2 = new System.Windows.Forms.TextBox();
        this.SuspendLayout();
        // 
        // comboBox1
        // 
        this.comboBox1.FormattingEnabled = true;
        this.comboBox1.Items.AddRange(new object[] {
        "Audi",
        "Fiat",
        "Ford",
        "VW"});
        this.comboBox1.Location = new System.Drawing.Point(87, 12);
        this.comboBox1.Name = "comboBox1";
        this.comboBox1.Size = new System.Drawing.Size(193, 21);
        this.comboBox1.TabIndex = 0;
        // 
        // label1
        // 
        this.label1.AutoSize = true;
        this.label1.Location = new System.Drawing.Point(1, 15);
        this.label1.Name = "label1";
        this.label1.Size = new System.Drawing.Size(38, 13);
        this.label1.TabIndex = 1;
        this.label1.Text = "Brand:";
        // 
        // label2
        // 
        this.label2.AutoSize = true;
        this.label2.Location = new System.Drawing.Point(1, 64);
        this.label2.Name = "label2";
        this.label2.Size = new System.Drawing.Size(34, 13);
        this.label2.TabIndex = 2;
        this.label2.Text = "Type:";
        // 
        // textBox1
        // 
        this.textBox1.Location = new System.Drawing.Point(87, 61);
        this.textBox1.Name = "textBox1";
        this.textBox1.Size = new System.Drawing.Size(193, 20);
        this.textBox1.TabIndex = 3;
        // 
        // textBox2
        // 
        this.textBox2.Location = new System.Drawing.Point(12, 110);
        this.textBox2.Multiline = true;
        this.textBox2.Name = "textBox2";
        this.textBox2.ReadOnly = true;
        this.textBox2.Size = new System.Drawing.Size(268, 144);
        this.textBox2.TabIndex = 4;
        // 
        // Form2
        // 
        this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
        this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
        this.ClientSize = new System.Drawing.Size(292, 266);
        this.Controls.Add(this.textBox2);
        this.Controls.Add(this.textBox1);
        this.Controls.Add(this.label2);
        this.Controls.Add(this.label1);
        this.Controls.Add(this.comboBox1);
        this.Name = "Form2";
        this.Text = "Form2";
        this.ResumeLayout(false);
        this.PerformLayout();

    }

    #endregion

    private System.Windows.Forms.ComboBox comboBox1;
    private System.Windows.Forms.Label label1;
    private System.Windows.Forms.Label label2;
    private System.Windows.Forms.TextBox textBox1;
    private System.Windows.Forms.TextBox textBox2;
}

Form2.cs

public partial class Form2 : Form
{
    private string[] types_audi = new string[] { "A4" };
    private string[] types_ford = new string[] { "Mustang", "Focus" };
    private string[] types_fiat = new string[] { "Punto", "500" };
    private string[] types_vw = new string[] { "Golf" };
    private List<string[]> types = new List<string[]>();

    public Form2()
    {
        InitializeComponent();

        this.types.Add(this.types_audi);
        this.types.Add(this.types_ford);
        this.types.Add(this.types_fiat);
        this.types.Add(this.types_vw);

        this.textBox1.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
        this.textBox1.AutoCompleteSource = AutoCompleteSource.CustomSource;
        this.textBox1.AutoCompleteCustomSource = new AutoCompleteStringCollection();
        this.textBox1.AutoCompleteCustomSource.AddRange(this.types_audi);
        this.textBox1.AutoCompleteCustomSource.AddRange(this.types_fiat);
        this.textBox1.AutoCompleteCustomSource.AddRange(this.types_ford);
        this.textBox1.AutoCompleteCustomSource.AddRange(this.types_vw);

        this.textBox1.Enter += new EventHandler(this.textBox1_Enter);
        this.textBox1.Leave += new EventHandler(this.textBox1_Leave);
        this.comboBox1.Select();
    }

    private void textBox1_Leave(object sender, EventArgs e)
    {
        this.textBox2.Clear();
    }

    private void textBox1_Enter(object sender, EventArgs e)
    {
        // reset AutoCompleteCustomSource
        this.textBox1.AutoCompleteCustomSource.Clear();

        switch (this.comboBox1.SelectedItem as string)
        {
            case "Audi":
                this.textBox1.AutoCompleteCustomSource.AddRange(this.types_audi);
                break;
            case "Ford":
                this.textBox1.AutoCompleteCustomSource.AddRange(this.types_ford);
                break;
            case "Fiat":
                this.textBox1.AutoCompleteCustomSource.AddRange(this.types_fiat);
                break;
            case "VW":
                this.textBox1.AutoCompleteCustomSource.AddRange(this.types_vw);
                break;
            default:
                this.textBox1.AutoCompleteCustomSource.AddRange(this.types_audi);
                this.textBox1.AutoCompleteCustomSource.AddRange(this.types_fiat);
                this.textBox1.AutoCompleteCustomSource.AddRange(this.types_ford);
                this.textBox1.AutoCompleteCustomSource.AddRange(this.types_vw);
                break;
        }

        this.textBox2.Text = "Possible values: " + Environment.NewLine;

        foreach (var val in this.textBox1.AutoCompleteCustomSource)
        {
            this.textBox2.Text += Environment.NewLine + val;
        }
    }
}

1 个答案:

答案 0 :(得分:0)

您可以创建一个新的字符串对象来存储组合框中以前选择的项目,如果组合中的所选项目与之前选择的项目不同,则清除textBox1_Enter方法中的textBox1,然后设置之前选择的项目到当前所选项目。

它应该是这样的:

private void textBox1_Enter(object sender, EventArgs e)
{
    // reset AutoCompleteCustomSource
    var selectedItem = comboBox1.SelectedItem as string;

    if (string.Compare(this.previouslySelectedItem, selectedItem) != 0)
    {
        this.textBox1.Clear();
        this.previouslySelectedItem = selectedItem;
    }

    this.textBox1.AutoCompleteCustomSource.Clear();

    switch (this.comboBox1.SelectedItem as string)
    {
        case "Audi":
            this.textBox1.AutoCompleteCustomSource.AddRange(this.types_audi);
            break;
        case "Ford":
            this.textBox1.AutoCompleteCustomSource.AddRange(this.types_ford);
            break;
        case "Fiat":
            this.textBox1.AutoCompleteCustomSource.AddRange(this.types_fiat);
            break;
        case "VW":
            this.textBox1.AutoCompleteCustomSource.AddRange(this.types_vw);
            break;
        default:
            this.textBox1.AutoCompleteCustomSource.AddRange(this.types_audi);
            this.textBox1.AutoCompleteCustomSource.AddRange(this.types_fiat);
            this.textBox1.AutoCompleteCustomSource.AddRange(this.types_ford);
            this.textBox1.AutoCompleteCustomSource.AddRange(this.types_vw);
            break;
    }

    this.textBox2.Text = "Possible values: " + Environment.NewLine;

    foreach (var val in this.textBox1.AutoCompleteCustomSource)
    {
        this.textBox2.Text += Environment.NewLine + val;
    }
}