如何在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秒。
有没有最快的方法来解决这个问题?
答案 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();
}