带有数据库

时间:2017-08-05 07:48:44

标签: c# .net winforms linq-to-sql

如何在c#winform中实现动态自动完成文本框?

例如,在我的应用程序中有一个名为txtbox_mobileno的文本框。 我想绑定移动号码(来自名为customer的数据库表)与txtbox_mobileno。 表客户有超过100,000条记录。客户在申请时输入手机号码时需要建议清单。

所以我尝试在textchanged事件

上实现以下代码
if (txtbox_mobileno.TextLength >3)
{

cmd.CommandText = "SELECT  TOP 20 MobileNo FROM Customer WHERE MobileNo LIKE'" + txtbox_mobileno.Text+"%'";
SqlDataReader dr;
dr = RunSqlReturnDR(cmd);//return value
 if (dr.HasRows)
 {
    while (dr.Read())
    {
   C.Add(dr[0].ToString()); //AutoCompleteStringCollection C = new AutoCompleteStringCollection();
     }
  }
 dr.Close();
 txtbox_mobileno.AutoCompleteMode = AutoCompleteMode.Suggest;
 txtbox_mobileno.AutoCompleteSource = AutoCompleteSource.CustomSource;
 txtbox_mobileno.AutoCompleteCustomSource = C;
}

我想仅在文本框中包含3个以上的字母时才显示建议列表 当尝试绑定加载事件时,用文本框建议列表

绑定数据大约需要5分钟

Sql server查询执行时间仅为3秒。

有没有最快的方法来解决这个问题?

2 个答案:

答案 0 :(得分:0)

我不确定您是否能够在应用程序开头抓取所有手机号码,或者至少在您的数据输入表单加载时抓取,但如果是这样,可能更容易将所有号码加载到桶中前三个字符是数字列表的关键字。即使你有1,000,000个数字,你只能说30 MB的数据(假设我的数学正确),所以你不应该在这方面遇到任何问题。你可以做这样的事情来建立你的桶。顺便说一句,我也不知道你得到多少数字有相同的前三位数,所以我可能会在这段代码中构建非常大的自动完成列表,这将是另一个问题。你的代码只撤回前20名,你可以修改这段代码只保留前20或类似的东西。

var buckets = new Dictionary<string, List<string>>();
cmd.CommandText = "SELECT MobileNo FROM Customer";
SqlDataReader dr = RunSqlReturnDR(cmd);
if (dr.HasRows)
{
    while (dr.Read())
    {
        var number = dr[0].ToString();
        var key = number.Substring(0, 3);
        List<string> numbers = null;
        if(!buckets.TryGetValue(key, out numbers))
        {
            numbers = new List<string>();                 
        }
        numbers.Add(number);
    }
}
dr.Close();

然后在您的事件处理程序中,您只需要执行以下操作:

if (txtbox_mobileno.Text.Length == 3)
{
    List<string> numbers;
    if (_buckets.TryGetValue(txtbox_mobileno.Text, out numbers)
    {
        var ac = new AutoCompleteStringCollection();
        ac.AddRange(numbers.ToArray());
        txtbox_mobileno.AutoCompleteMode = AutoCompleteMode.Suggest;
        txtbox_mobileno.AutoCompleteSource = AutoCompleteSource.CustomSource;
        txtbox_mobileno.AutoCompleteCustomSource = ac;
    }
}

您可能会增强此功能的其他方法是在您获取数字的查询中添加订单,然后您应该能够遍历这些值,只需在前三次更改时创建新列表数字。这样可以更容易地构建数组字典而不是列表字典,这将有助于您的自动完成框。我还有一段时间没有写过很多数据库代码,所以我只保留你发布的代码,以便从数据库中获取数据。可能有更好的方法从数据库中读取数据。

答案 1 :(得分:-1)

Try use a timer to fire query, and a Thread to execute, see:

    private void textBox1_TextChanged(object sender, EventArgs e)
    {
        timer1.Enabled = false;
        timer1.Enabled = true;
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        timer1.Enabled = false;

        string filter = txtbox_mobileno.Text;

        Thread t = new Thread(() => {

            cmd.CommandText = "SELECT  TOP 20 MobileNo FROM Customer WHERE MobileNo LIKE '" + filter + "%'";
            SqlDataReader dr;
            dr = RunSqlReturnDR(cmd);//return value
            if (dr.HasRows)
            {
                while (dr.Read())
                {
                    C.Add(dr[0].ToString()); //AutoCompleteStringCollection C = new AutoCompleteStringCollection();
                }
            }

            dr.Close();

            txtbox_mobileno.Invoke((MethodInvoker)delegate {
                txtbox_mobileno.AutoCompleteMode = AutoCompleteMode.Suggest;
                txtbox_mobileno.AutoCompleteSource = AutoCompleteSource.CustomSource;
                txtbox_mobileno.AutoCompleteCustomSource = C;
            });
        });


        t.Start();
    }