我正在用C#开发一个MySQL编辑器,我这样做是为了让你可以通过双击名称来重命名数据库。不过,出于某种原因,如果我尝试重命名已重命名的部分,AfterLabelEdit 会执行两次。
例
我有一个名为"test_db"的数据库。我双击它后,它会完美重命名并更新服务器端的名称。但是当我第二次尝试重命名数据库时,它会执行两次 AfterLabelEdit 事件,导致 SQL 数据库尝试将数据库重命名为自己,从而引发错误。更糟糕的是,它会执行剩余的代码,进而完全删除数据库。
《守则》
private void ListView1_MouseDoubleClick(object sender, MouseEventArgs e)
{
ListViewItem selecteditem_ = listView1.SelectedItems[0];
originaldbname_ = listView1.SelectedItems[0].Text;
selecteditem_.BeginEdit();
listView1.AfterLabelEdit += ListView1_AfterLabelEdit;
}
这是事件本身(省略(:
private void ListView1_AfterLabelEdit(object sender, LabelEditEventArgs e)
{
MySqlCommand rename_db = new MySqlCommand("CREATE DATABASE `" + e.Label + "`; ", dbconnect);
try
{
MySqlDataReader reader;
reader = rename_db.ExecuteReader();
while(reader.Read())
{
}
reader.Close();
}
catch
{
MessageBox.Show("Rename failed. Maybe you already have a database named " + e.Label + "?");
}
if (treeView1.Nodes[0].Nodes[originaldbname_].Nodes.Count == 0)
{
MySqlDataReader reader;
rename_db.CommandText = "DROP DATABASE `" + originaldbname_ + "`";
reader = rename_db.ExecuteReader();
reader.Close();
treeView1.Nodes[0].Nodes[originaldbname_].Name = e.Label;
originaldbname_ = e.Label;
}
else
{
MySqlDataReader reader;
for (int i = 0; i < treeView1.Nodes[0].Nodes[originaldbname_].Nodes.Count; i++)
{
string tablename_ = treeView1.Nodes[0].Nodes[originaldbname_].Nodes[i].Name;
rename_db.CommandText = "ALTER TABLE `" + originaldbname_ + "`." + tablename_ + " RENAME `" + e.Label + "`." + tablename_ + "";
}
reader = rename_db.ExecuteReader();
while (reader.Read())
{
}
reader.Close();
rename_db.CommandText = "DROP DATABASE `" + originaldbname_ + "`";
reader = rename_db.ExecuteReader();
reader.Close();
treeView1.Nodes[0].Nodes[originaldbname_].Name = e.Label;
originaldbname_ = e.Label;
treeView1.Update();
listView1.Refresh();
treeView1.Refresh();
}
}
主要问题是ListView1_MouseDoubleClick
事件处理程序内部的以下行,每次双击时,都会附加一个新的事件处理程序,您第三次尝试重命名,您将看到AfterLabelEdit
触发三次。
listView1.AfterLabelEdit += ListView1_AfterLabelEdit;
将此行移出ListView1_MouseDoubleClick
事件处理程序,将其放在代码开头的表单构造函数/表单加载/某处。
public Form1(){
InitializeComponent();
listView1.AfterLabelEdit += ListView1_AfterLabelEdit;
}
无论 catch 如何,ListView1_AfterLabelEdit 中的 try/catch 块之后的所有内容都将始终执行,因为您在显示 MessageBox 后没有退出。 您需要退货;以阻止其余代码触发。
试试这个:
catch
{
MessageBox.Show("Rename failed. Maybe you already have a database named ?");
return;
}
每次双击列表项时,都会向 AfterLabelEdit
事件添加新的处理程序。
例如,当第一次单击某个项目时,将执行以下行
listView1.AfterLabelEdit += ListView1_AfterLabelEdit;
因此,现在一个事件处理程序附加到事件。再次单击该项时,另一个处理程序将附加到事件。因此,该事件被触发了两次。如果再次双击该项,事件将触发三次。
一个简单的解决方法是在添加事件处理程序(listView1.AfterLabelEdit -= ListView1_AfterLabelEdit;
(之前将其删除,如下所示。
private void ListView1_MouseDoubleClick(object sender, MouseEventArgs e)
{
ListViewItem selecteditem_ = listView1.SelectedItems[0];
originaldbname_ = listView1.SelectedItems[0].Text;
selecteditem_.BeginEdit();
listView1.AfterLabelEdit -= ListView1_AfterLabelEdit;
listView1.AfterLabelEdit += ListView1_AfterLabelEdit;
}