【问题标题】:Efficient way to avoid duplicated code of buttons clicks避免重复的按钮点击代码的有效方法
【发布时间】:2012-07-01 23:09:31
【问题描述】:

假设我有 2 个按钮,它们应该在不同的对象上执行相同的操作。

目前我将所有需要的引用传递给这样的方法:

    private void sub1_add_to_db_btn_Click(object sender, EventArgs e)
    {
        Add_Substance_To_Database(
            substanse1, sub1_add_to_db_btn, sub2_add_to_db_btn, sub1_found_in_db_list,
            sub2_found_in_db_list, false, sub1_listBox, sub2_listBox);
    }

    private void sub2_add_to_db_btn_Click(object sender, EventArgs e)
    {
        Add_Substance_To_Database(
            substanse2, sub2_add_to_db_btn, sub1_add_to_db_btn, sub2_found_in_db_list,
            sub1_found_in_db_list, false, sub2_listBox, sub1_listBox);
    }

我想知道是否有其他更有效的方法来做到这一点。谢谢。

编辑:

这就是我的一些代码的样子,这让我很疯狂!!!

private void sub1_add_to_db_btn_Click(object sender, EventArgs e)
    {
        Add_Substance_To_Database(substanse1, sub1_add_to_db_btn, sub2_add_to_db_btn,
            sub1_found_in_db_list, sub2_found_in_db_list, false, sub1_listBox, sub2_listBox);
    }

    private void sub2_add_to_db_btn_Click(object sender, EventArgs e)
    {
        Add_Substance_To_Database(substanse2, sub2_add_to_db_btn, sub1_add_to_db_btn,
            sub2_found_in_db_list, sub1_found_in_db_list, false, sub2_listBox, sub1_listBox);
    }

    private void sub1_edit_name_btn_Click(object sender, EventArgs e)
    {
        Add_Substance_To_Database(substanse1, sub1_add_to_db_btn, sub2_add_to_db_btn,
            sub1_found_in_db_list, sub2_found_in_db_list, true, sub1_listBox, sub2_listBox);
    }

    private void sub2_edit_name_btn_Click(object sender, EventArgs e)
    {
        Add_Substance_To_Database(substanse2, sub2_add_to_db_btn, sub1_add_to_db_btn,
            sub2_found_in_db_list, sub1_found_in_db_list, true, sub2_listBox, sub1_listBox);
    }

    private void sub1_delete_from_db_btn_Click(object sender, EventArgs e)
    {
        Delete_Substance_From_DB(sub1_listBox,
            sub2_listBox,sub2_list_is_from_file,sub1_delete_from_db_btn,
            sub2_delete_from_db_btn);
    }

    private void sub2_delete_from_db_btn_Click(object sender, EventArgs e)
    {
        Delete_Substance_From_DB(sub2_listBox,
            sub1_listBox,sub1_list_is_from_file,sub2_delete_from_db_btn,
            sub1_delete_from_db_btn);
    }

例如: 如果我想删除一种物质,我需要从两个列表中删除它并从其他列表中删除它,将选择更改为下一个物质等...

【问题讨论】:

  • 您可以将同一个事件处理程序连接到多个按钮,然后根据发送者选择要运行的 Add_Substance_To_Database 变体。但是,您实际上可能会发现更改 UI 以使 material1 和其他变量参数来自下拉列表等控件会更好。您有可以展示的 GUI 示例吗?
  • 出于隐私原因,我不想发布 GUI。问题是,为了方便起见,我必须将 2 个物质列表并排比较。从一个列表中选择一种物质的每次选择都将执行一些与从另一个列表中选择的其他物质相关的比较操作。在每个列表旁边还有一些按钮,例如:删除、编辑、添加到数据库等等......每个按钮都有类似于我上面写的方法。
  • 为什么要将按钮和列表框传递给函数?我可以理解的列表框,因为您可能正在查看物质 1 列表和物质 2 列表中的内容。严格来说,如果您让用户从每个列表中选择两个项目,您可以只将所选项目和列表传递给您的方法 - 例如,您可以在每个列表中搜索 Add_Substance_To_Database 中的物质。
  • 传递按钮的原因是因为列表框是多用途的。当我按下一个名为“从数据库显示”的按钮时,列表显示来自数据库而不是本地文件的物质,并且按钮更改为“从文件显示”。此外,当列表处于数据库模式时,必须禁用“添加到数据库”按钮。大多数情况下,我的所有按钮都启用/禁用到列表的当前“状态”。这就是为什么我需要将相关按钮引用传递给每个方法。

标签: c# winforms methods code-duplication


【解决方案1】:

最终我遵循了我自己的建议...... 我创建了一个包含所有控制器的对象数组,并向控制器事件处理程序添加了相同的方法。在方法中我只是根据发送者选择正确的控制器。

substance1_controllers = new object[]{
            sub1_main_listbox, sub1_peaks_list,sub1_found_in_db_list,
            sub1_similar_in_db_list, sub1_eigenvector_list,
            sub1_sourse_switch_btn, sub1_folder_btn,sub1_add_to_db_btn,
            sub1_edit_name_btn,sub1_delete_btn, sub1_picture_box,
            chart_peaks.Series[0], chart_compare.Series[0], true, -1};
substance2_controllers = new object[]{
            sub2_main_listbox, sub2_peaks_list, sub2_found_in_db_list,
            sub2_similar_in_db_list,sub2_eigenvector_list,
            sub2_sourse_switch_btn, sub2_folder_btn, sub2_add_to_db_btn,
            sub2_edit_name_btn,sub2_delete_btn, sub2_picture_box, 
            chart_peaks.Series[1],chart_compare.Series[1], true, -1};

这种方式可能看起来更难维护,但我个人觉得在这张表的帮助下维护和使用它非常舒服(而且看起来很棒):

        // [0]  - Main Listbox
        // [1]  - Peaks Listbox
        // [2]  - Found in Database Listbox
        // [3]  - Found similar Listbox
        // [4]  - Eigenvectors Listbox
        // [5]  - Switch sourse Button
        // [6]  - Change Folder Button
        // [7]  - Add to Database Button
        // [8]  - Edit Name Button
        // [9]  - Delete Button
        // [10] - Picture Box
        // [11] - Peaks Chart Series
        // [12] - Compare Chart Series
        // [13] - List is from File Boolean
        // [14] - Previous Selected Index

方法示例:

void Delete_Substance_From_DB(object sender, EventArgs e)
    {
        object[] controller;
        object[] other_controller;
        if (((Button)sender).Name == "sub1_delete_btn")
        {
            controller = substance1_controllers;
            other_controller = substance2_controllers;
        }
        else
        {
            controller = substance2_controllers;
            other_controller = substance1_controllers;
        }
    }

使用例子:

if (((ListBox)other_controller[0]).Items.Count != 0)
        {
            if (((ListBox)other_controller[0]).Items.Count == index2)
            {
                ((ListBox)other_controller[0]).SelectedIndex = index2 - 1;
            }
            else
            {
               ((ListBox)other_controller[0]).SelectedIndex = index2;
            }
            Main_Listbox_Index_Changed(((ListBox)other_controller[0]), null);
        }

【讨论】:

    【解决方案2】:

    这根本不是代码重复的情况。重构这样的案例只会使它:

    • 更复杂
    • 不可读

    请看:Any valid reason for code duplication?

    编辑:

    如果您在事件处理程序中有更多重复的“肉”,我会建议可能有所不同。但是您将所有内容都拉到了Add_Substance_To_Database,因此您已经成功地对代码进行了重复数据删除。

    【讨论】:

    • 请看编辑后的帖子...你认为我应该这样吗?您如何看待我在第一个答案的评论中提出的建议?
    • 我会留在我的位置上,会问你:不会让你发疯的代码是什么样的?为什么它让你发疯?您是否觉得它不美观,或者您觉得它难以维护,或者您认为它难以调试?重构这种情况(在您的情况下,某种表适合保存参数列表)必须根据需要进行驱动。
    【解决方案3】:

    事件处理程序可能是少数控件之一,在发送者中您有按钮控件,它调用事件,将其转换为 Button 类并使用 tham 作为方法的参数

    var button = 作为按钮的发送者;

    Add_Substance_To_Database( substanse2,按钮,sub1_add_to_db_btn,sub2_found_in_db_list, sub1_found_in_db_list, false, sub2_listBox, sub1_listBox);

    对于其他参数,您可以使用属性标签,它是用于开发目的的对象

    【讨论】:

      【解决方案4】:

      鉴于您将不同的值传递给Add_Substance_To_Database,您现在拥有的可能是您所希望的最可维护的代码。

      您可以将一个事件处理程序附加到两个按钮,但您必须确定按下了哪个按钮并传递相关参数:

      if (sender == button1)
      {
          Add_Substance_To_Database(
              substanse1, sub1_add_to_db_btn, sub2_add_to_db_btn, sub1_found_in_db_list,
              sub2_found_in_db_list, false, sub1_listBox, sub2_listBox);
      }
      else
      {
          Add_Substance_To_Database(
              substanse2, sub2_add_to_db_btn, sub1_add_to_db_btn, sub2_found_in_db_list,
              sub1_found_in_db_list, false, sub2_listBox, sub1_listBox);
      }
      

      这让你一无所获。

      【讨论】:

      • +1 同意;这感觉就像改变 GUI 可以极大地简化保存逻辑的情况
      • 我在想将所有控件保存到对象数组然后将其传递给函数会更有效(从编码器的角度来看),例如: if (sender == button1) Add_Substance_To_Database (array1).. else array2.. 然后每个方法将通过强制转换仅“提取”相关控件?
      猜你喜欢
      • 2011-09-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-01
      • 2014-05-07
      相关资源
      最近更新 更多