ListView AfterLabelEdit两次射击

时间:2018-03-13 20:23:22

标签: c# .net listview event-handling

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

这是事件本身(ommited):

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();

        }
    }

3 个答案:

答案 0 :(得分:1)

主要问题是ListView1_MouseDoubleClick事件处理程序中的以下行,每次双击时,都会附加一个新的事件处理程序,您尝试第三次重命名,您将看到{{1}火三次。

AfterLabelEdit

将此行移出listView1.AfterLabelEdit += ListView1_AfterLabelEdit; 事件处理程序,将其放在代码开头的表单构造函数/表单load / some中。

ListView1_MouseDoubleClick

答案 1 :(得分:0)

ListView1_AfterLabelEdit中try / catch块之后的所有内容将始终执行,无论catch是什么,因为在显示MessageBox后您没有退出。你需要回报;在那里停止其余的代码被解雇。

试试这个:

catch
    { 
        MessageBox.Show("Rename failed. Maybe you already have a database named ?");
        return;
    }

答案 2 :(得分:0)

每次双击列表项时,新的处理程序都会添加到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;
}