ListView 控件在通过文本框搜索后多次显示一个值
ListView control showing one value multiple times after search through textbox
我目前正在开发 WinForms 应用程序,其中在表单上有一个用于搜索的文本框和一个 ListView 控件,其中将根据用户的输入从数据库中填充数据。
下面是在文本框控件
上实现TextChanged
事件的代码
private void tbSearchGlassOnShell_TextChanged(object sender, EventArgs e)
{
Form1 form = new Form1();
string cmdString = string.Empty;
try
{
string connString = string.Format("Server={0};Username={1};Database={2};Port={3};Password={4};",
form.Tbhostname, form.Tbusername, form.Tbdatabase, form.Tbport, form.Tbpassword);
MySqlConnection conn = new MySqlConnection(connString);
conn.Open();
cmdString = "SELECT shell_glass.shell_glass_id,shell.shell_name,glass.glass_name," +
"shell_glass.shell_glass_quantity,shell_glass.shell_glass_ordernumber," +
"shell_glass.shell_glass_datetime,shell_glass.user_id FROM shell_glass " +
"JOIN shell using (shell_id) JOIN glass using (glass_id)" +
"WHERE LOWER(glass.glass_name) LIKE '%" + tbSearchGlassOnShell.Text.ToLower() + "%'";
MySqlCommand command = new MySqlCommand(cmdString, conn);
MySqlDataReader reader = command.ExecuteReader();
while(reader.Read())
{
ListViewItem item = new ListViewItem(reader["shell_glass_id"].ToString());
item.SubItems.Add(reader["shell_name"].ToString());
item.SubItems.Add(reader["glass_name"].ToString());
item.SubItems.Add(reader["shell_glass_quantity"].ToString());
item.SubItems.Add(reader["shell_glass_ordernumber"].ToString());
item.SubItems.Add(reader["shell_glass_datetime"].ToString());
item.SubItems.Add(reader["user_id"].ToString());
lvSearchGlassOnShell.Items.Add(item);
}
reader.Close();
}
catch (MySqlException ex)
{
form.TbSetupLog.AppendText("MySqlExepction: " + ex.Message + Environment.NewLine);
}
catch (Exception ex)
{
form.TbSetupLog.AppendText("Exception: " + ex.Message + Environment.NewLine);
}
}
出于某种原因,ListView 控件在用户输入后多次显示相同的值,如下图所示
问题:如何实现用户输入后只有一个值不重复?
TextBox 中键入的每个字符都会调用 TextChanged 事件,因此在您键入第一个字母时执行搜索,然后在您键入第二个字母时执行另一个搜索,依此类推。您永远不会清除 ListView 项目集合,因此每次搜索都会在列表视图中添加另一个条目。
要解决您眼前的问题,只需致电
lvSearchGlassOnShell.Items.Clear();
在进入 reader 循环之前。
但是上面的代码还有其他问题。严重的是 the Sql Injection 成为可能,因为您连接字符串以构建 sql 命令。
相反,您需要以这种方式使用参数
try
{
lvSearchGlassOnShell.Items.Clear();
string connString = string.Format("Server={0};Username={1};Database={2};Port={3};Password={4};",
form.Tbhostname, form.Tbusername, form.Tbdatabase, form.Tbport, form.Tbpassword);
string cmdString = @"SELECT shell_glass.shell_glass_id,
shell.shell_name,glass.glass_name,
shell_glass.shell_glass_quantity,
shell_glass.shell_glass_ordernumber,
shell_glass.shell_glass_datetime,
shell_glass.user_id
FROM shell_glass
JOIN shell using (shell_id)
JOIN glass using (glass_id)
WHERE LOWER(glass.glass_name) LIKE @name";
using(MySqlConnection conn = new MySqlConnection(connString))
using(MySqlCommand command = new MySqlCommand(cmdString, conn))
{
conn.Open();
command.Parameters.Add("@name", MySqlDbType.Text).Value = tbSearchGlassOnShell.Text;
MySqlDataReader reader = command.ExecuteReader();
....
}
}
catch(Exception ex)
....
这里我删除了输入文本的连接,并放置了一个参数占位符以避免 SqlInjection 问题。还要注意如何将连接作为一次性对象包含在 using 语句中以正确清理该对象使用的资源
我目前正在开发 WinForms 应用程序,其中在表单上有一个用于搜索的文本框和一个 ListView 控件,其中将根据用户的输入从数据库中填充数据。
下面是在文本框控件
上实现TextChanged
事件的代码
private void tbSearchGlassOnShell_TextChanged(object sender, EventArgs e)
{
Form1 form = new Form1();
string cmdString = string.Empty;
try
{
string connString = string.Format("Server={0};Username={1};Database={2};Port={3};Password={4};",
form.Tbhostname, form.Tbusername, form.Tbdatabase, form.Tbport, form.Tbpassword);
MySqlConnection conn = new MySqlConnection(connString);
conn.Open();
cmdString = "SELECT shell_glass.shell_glass_id,shell.shell_name,glass.glass_name," +
"shell_glass.shell_glass_quantity,shell_glass.shell_glass_ordernumber," +
"shell_glass.shell_glass_datetime,shell_glass.user_id FROM shell_glass " +
"JOIN shell using (shell_id) JOIN glass using (glass_id)" +
"WHERE LOWER(glass.glass_name) LIKE '%" + tbSearchGlassOnShell.Text.ToLower() + "%'";
MySqlCommand command = new MySqlCommand(cmdString, conn);
MySqlDataReader reader = command.ExecuteReader();
while(reader.Read())
{
ListViewItem item = new ListViewItem(reader["shell_glass_id"].ToString());
item.SubItems.Add(reader["shell_name"].ToString());
item.SubItems.Add(reader["glass_name"].ToString());
item.SubItems.Add(reader["shell_glass_quantity"].ToString());
item.SubItems.Add(reader["shell_glass_ordernumber"].ToString());
item.SubItems.Add(reader["shell_glass_datetime"].ToString());
item.SubItems.Add(reader["user_id"].ToString());
lvSearchGlassOnShell.Items.Add(item);
}
reader.Close();
}
catch (MySqlException ex)
{
form.TbSetupLog.AppendText("MySqlExepction: " + ex.Message + Environment.NewLine);
}
catch (Exception ex)
{
form.TbSetupLog.AppendText("Exception: " + ex.Message + Environment.NewLine);
}
}
出于某种原因,ListView 控件在用户输入后多次显示相同的值,如下图所示
问题:如何实现用户输入后只有一个值不重复?
TextBox 中键入的每个字符都会调用 TextChanged 事件,因此在您键入第一个字母时执行搜索,然后在您键入第二个字母时执行另一个搜索,依此类推。您永远不会清除 ListView 项目集合,因此每次搜索都会在列表视图中添加另一个条目。
要解决您眼前的问题,只需致电
lvSearchGlassOnShell.Items.Clear();
在进入 reader 循环之前。
但是上面的代码还有其他问题。严重的是 the Sql Injection 成为可能,因为您连接字符串以构建 sql 命令。
相反,您需要以这种方式使用参数
try
{
lvSearchGlassOnShell.Items.Clear();
string connString = string.Format("Server={0};Username={1};Database={2};Port={3};Password={4};",
form.Tbhostname, form.Tbusername, form.Tbdatabase, form.Tbport, form.Tbpassword);
string cmdString = @"SELECT shell_glass.shell_glass_id,
shell.shell_name,glass.glass_name,
shell_glass.shell_glass_quantity,
shell_glass.shell_glass_ordernumber,
shell_glass.shell_glass_datetime,
shell_glass.user_id
FROM shell_glass
JOIN shell using (shell_id)
JOIN glass using (glass_id)
WHERE LOWER(glass.glass_name) LIKE @name";
using(MySqlConnection conn = new MySqlConnection(connString))
using(MySqlCommand command = new MySqlCommand(cmdString, conn))
{
conn.Open();
command.Parameters.Add("@name", MySqlDbType.Text).Value = tbSearchGlassOnShell.Text;
MySqlDataReader reader = command.ExecuteReader();
....
}
}
catch(Exception ex)
....
这里我删除了输入文本的连接,并放置了一个参数占位符以避免 SqlInjection 问题。还要注意如何将连接作为一次性对象包含在 using 语句中以正确清理该对象使用的资源