列表视图后标签编辑触发两次



我正在用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;
}    

最新更新