首页 > 解决方案 > C# - 防止在后续点击中调用按钮

问题描述

我有这个表格:

在此处输入图像描述

如果我按下右侧的黄色按钮,表格将变为:

在此处输入图像描述

当我修改元素并按“SALVA”按钮保存更改时,我得到了正确的行为:出现一个消息框,告诉我所有内容都已正确保存。如果现在我再次按下黄色按钮(不退出表单)并修改一个元素(它可能是相同的或另一个)我会得到一个不好的行为:消息框出现两次。如果我再做一次同样的事情,消息框会连续出现 3 次,以此类推。

查看函数调用者(我使用 this Console.WriteLine((new System.Diagnostics.StackTrace()).GetFrame(1).GetMethod().Name)),我发现在第一次调用时,类型是 OnClick,从第二次调用开始,类型更改为 Invoke。结果,函数 SaveChange() 被多次调用。


我能做些什么来避免这种行为?

这是 cheActionsTable类代码:

using Google.Protobuf.WellKnownTypes;
using office_software.DBModel;
using office_software.Forms;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows.Forms;

namespace office_software.Table {
    class ActionsTable<T, L> : TableLayoutPanel {

        private readonly int y;
        private readonly Form caller;
        private readonly DBEntities dbEntities;

        public ActionsTable(DBEntities dbEntities, Form caller, TableLayoutPanel parent, int x, int y, List<bool> type) {
            this.y = y;
            this.caller = caller;
            this.dbEntities = dbEntities;
            parent.Controls.Add(BuildTable(parent, type), x, y);
        }

        private TableLayoutPanel BuildTable(TableLayoutPanel parent, List<bool> type) {
            TableLayoutPanel actionPanel = new TableLayoutPanel {
                RowCount = 1,
                ColumnCount = type.Where(x => x is true).ToList().Count,
                Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Bottom,
            };

            for (int k = 0; k < actionPanel.ColumnCount; k++) actionPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, (100 / actionPanel.ColumnCount)));
            for (int k = 0; k < actionPanel.RowCount; k++) actionPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));

            int m = 0;
            for (int l = 0; l < type.Count; l++) {
                if (type[l]) {
                    Button button = new Button {
                        Anchor = AnchorStyles.None,
                        Height = 15,
                        Width = 15,
                        Name = $"{y}-{l}",
                        FlatStyle = FlatStyle.Flat,
                        BackColor = Constants.Constants.ACTIONS[l].color
                    };

                    ToolTip toolTip = new ToolTip();
                    toolTip.SetToolTip(button, Constants.Constants.ACTIONS[l].actionName);

                    button.Click += (s, e) => ActionRow(s, e, parent);

                    actionPanel.Controls.Add(button, m, 0);
                    m++;
                }
            }

            return actionPanel;
        }

        private void ShowDetails(List<string> data) {
            if (typeof(L) != typeof(NullValue)) {
                if (typeof(L) == typeof(DetailsForm)) {
                    DetailsForm details = new DetailsForm(dbEntities, new string[]{ data[0] });
                    details.ShowDialog();
                }
                else if (typeof(L) == typeof(CommissionDetailsForm)) {
                    CommissionDetailsForm details = new CommissionDetailsForm(dbEntities, new string[] { data[0].TrimStart('C') });
                    details.ShowDialog();
                }
                else if (typeof(L) == typeof(ProductDetails)) {
                    ProductDetails details = new ProductDetails(dbEntities, new string[]{ data[0] });
                    details.ShowDialog();
                }
            }
        }

        private void ModifyDetails(List<string> data) {
            if (typeof(T) != typeof(NullValue)) {
                if (typeof(T) == typeof(ProductsForm)) {
                    ProductsForm form = ((ProductsForm)caller);
                    form.titleLabel.Text = "MODIFICA PRODOTTO";

                    form.undoButton.Show();
                    form.addButton.Hide();
                    form.saveButton.Show();
                    form.model.Enabled = false;

                    string _tmp = data[0];
                    product product = dbEntities.products.FirstOrDefault(x => x.model.Equals(_tmp));
                    form.device.Text = product.device;
                    form.brand.Text = product.brand;
                    form.model.Text = product.model;
                    form.from.Text = product.range_from.ToString();
                    form.to.Text = product.range_to.ToString();
                    form.um.Text = product.unit_measure;
                    form.output.Text = product.output;

                    if (product.accuracy_rdg is null) {
                        form.accuracyType.SelectedIndex = 0;
                        form.percValue.Text = product.accuracy_fs.ToString();
                    }
                    else {
                        form.accuracyType.SelectedIndex = 1;
                        string[] tmp = product.accuracy_rdg.Replace(" ", "").Split('+');
                        form.percValue.Text = tmp[0].TrimEnd('%');
                        form.fixedValue.Text = tmp[1];
                    }

                    form.undoButton.Click += UndoModify;
                    form.saveButton.Click += SaveChange;
                }
                else if (typeof(T) == typeof(CustomersForm)) {
                    CustomersForm form = ((CustomersForm)caller);
                    form.titleLabel.Text = "MODIFICA CLIENTE";

                    form.undoButton.Show();
                    form.addButton.Hide();
                    form.saveButton.Show();

                    string _tmp = data[0];
                    customer customer = dbEntities.customers.FirstOrDefault(x => x.name.Equals(_tmp, StringComparison.OrdinalIgnoreCase));

                    form.name.Text = customer.name;
                    form.vatNumber.Enabled = false;
                    form.vatNumber.Text = customer.vat_number;

                    form.undoButton.Click += UndoModify;
                    form.saveButton.Click += SaveChange;
                }
            }
        }

        private void UndoModify(object sender, EventArgs e) {
            if (typeof(T) != typeof(NullValue)) {
                if (typeof(T) == typeof(ProductsForm)) {
                    ProductsForm form = ((ProductsForm)caller);
                    form.titleLabel.Text = "NUOVO PRODOTTO";
                    form.titleLabel.Select();
                    form.undoButton.Hide();
                    form.saveButton.Hide();
                    form.addButton.Show();

                    form.model.Enabled = true;
                    form.HandleTextBox(null);
                }
                else if (typeof(T) == typeof(CustomersForm)) {
                    CustomersForm form = ((CustomersForm)caller);
                    form.titleLabel.Text = "NUOVO CLIENTE";
                    form.titleLabel.Select();
                    form.undoButton.Hide();
                    form.saveButton.Hide();
                    form.addButton.Show();
                }
            }
        }

        private void SaveChange(object sender, EventArgs e) {
            if (typeof(T) == typeof(ProductsForm)) {
                ProductsForm form = ((ProductsForm)caller);
                List<string> data = new List<string>();
                form.HandleTextBox(data);

                if (data.All(x => !string.IsNullOrEmpty(x))) {
                    product product = dbEntities.products.FirstOrDefault(p => p.model.Equals(form.model.Text, StringComparison.OrdinalIgnoreCase));

                    product.brand = form.brand.Text;
                    product.device = form.device.Text;
                    product.output = form.output.Text;
                    product.unit_measure = form.um.Text;
                    product.range_from = Convert.ToInt32(form.from.Text);
                    product.range_to = Convert.ToInt32(form.to.Text);
                    product.accuracy_fs = (form.accuracyType.SelectedIndex == 0) ? float.Parse(form.percValue.Text.Replace('.', ',')) : (float?)null;
                    product.accuracy_rdg = (form.accuracyType.SelectedIndex == 1) ? $"{form.percValue.Text}% + {form.fixedValue.Text}" : null;

                    dbEntities.SaveChanges();

                    MessageBox.Show("Prodotto modificato con successo.", "SUCCESSO", MessageBoxButtons.OK, MessageBoxIcon.Information);

                    form.productListTable.Controls[1].Dispose();
                    new CustomTable<ProductsForm, ProductDetails>(
                        dbEntities,
                        form,
                        form.productListTable,
                        new List<string> { "MODELLO", "SCALA", "USCITA" },
                        dbEntities.products.ToList().Select(x => new Row(x)).ToList(),
                        new List<bool> { true, true, true }
                    );

                    form.titleLabel.Text = "NUOVO PRODOTTO";
                    form.titleLabel.Select();
                    form.saveButton.Hide();
                    form.undoButton.Hide();
                    form.addButton.Show();
                }
                else MessageBox.Show("Tutti i campi sono obbligatori.", "ERRORE", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            else if (typeof(T) == typeof(CustomersForm)) {
                CustomersForm form = ((CustomersForm)caller);
                if (!string.IsNullOrEmpty(form.name.Text)) {
                    
                    customer customer = dbEntities.customers.FirstOrDefault(x => x.vat_number.Equals(form.vatNumber.Text, StringComparison.OrdinalIgnoreCase));
                    
                    customer.name = form.name.Text;

                    dbEntities.SaveChanges();
                    
                    MessageBox.Show("Cliente modificato con successo.", "SUCCESSO", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    /*
                    form.customerParent.Controls[1].Dispose();
                    new CustomTable<CustomersForm, NullValue>(
                        dbEntities,
                        form,
                        form.customerParent,
                        new List<string> { "NOME", "PARTITA IVA" },
                        dbEntities.customers.OrderBy(x => x.name).ToList().Select(i => new Row(i)).ToList(),
                        new List<bool> { false, true, true }
                    );

                    form.titleLabel.Text = "NUOVO CLIENTE";
                    form.titleLabel.Select();
                    form.saveButton.Hide();
                    form.undoButton.Hide();
                    form.addButton.Show();

                    form.vatNumber.Enabled = true;
                    form.vatNumber.Text = "";
                    form.name.Text = "";*/

                    Start start = new Start(dbEntities);
                    form.Hide();
                    start.ShowDialog();
                }
                else MessageBox.Show("Compirare tutti i campi.", "ERRORE", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void RemoveRow(List<string> data) {
            string tmp = data[0];
            if (typeof(T) != typeof(NullValue)) {
                if (typeof(T) == typeof(CustomersForm)) {
                    customer customer = dbEntities.customers.FirstOrDefault(x => x.name.Equals(tmp, StringComparison.OrdinalIgnoreCase));
                    
                    int existsCalibrations = dbEntities.calibrations.Where(x => x.commission.order.customer.name.Equals(customer.name)).Where(x => x.tests.Any()).Count();
                    if (existsCalibrations > 0) {
                        DialogResult dr = MessageBox.Show("Sono state trovate delle calibrazioni associate a questo cliente. Pocedendo con la sua eliminazione verranno persi tutti i dati ad esso associati. Si desidera procedere comunque?", "ATTENZIONE", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
                        if (dr != DialogResult.Yes) return;
                    }
                    else {
                        DialogResult dr = MessageBox.Show("Sicuro di voler eliminare questo cliente?", "ATTENZIONE", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
                        if (dr != DialogResult.Yes) return;
                    }

                    dbEntities.customers.Remove(customer);
                    dbEntities.SaveChanges();

                    MessageBox.Show("Cliente eliminato con successo.", "SUCCESSO", MessageBoxButtons.OK, MessageBoxIcon.Information);

                    ((CustomersForm)caller).customerParent.Controls[1].Dispose();
                    new CustomTable<CustomersForm, NullValue>(
                        dbEntities,
                        ((CustomersForm)caller),
                        ((CustomersForm)caller).customerParent,
                        new List<string> { "NOME", "PARTITA IVA" },
                        dbEntities.customers.OrderBy(x => x.name).ToList().Select(i => new Row(i)).ToList(),
                        new List<bool> { false, true, true }
                    );
                }
                else if (typeof(T) == typeof(ProductsForm)) {
                    product product = dbEntities.products.FirstOrDefault(x => x.model.Equals(tmp, StringComparison.OrdinalIgnoreCase));

                    int existsCalibrations = dbEntities.calibrations.Where(x => x.commission.model.Equals(product.model)).Where(x => x.tests.Any()).Count();
                    if (existsCalibrations > 0) {
                        DialogResult dr = MessageBox.Show("Sono state trovate delle calibrazioni associate a questo prodotto. Pocedendo con la sua eliminazione verranno persi tutti i dati ad esso associati. Si desidera procedere comunque?", "ATTENZIONE", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
                    if (dr != DialogResult.Yes) return;
                }
                else {
                    DialogResult dr = MessageBox.Show("Sicuro di voler eliminare questo prodotto?", "ATTENZIONE", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
                    if (dr != DialogResult.Yes) return;
                }

                dbEntities.products.Remove(product);
                dbEntities.SaveChanges();

                MessageBox.Show("Prodotto eliminato con successo.", "SUCCESSO", MessageBoxButtons.OK, MessageBoxIcon.Information);

                ((ProductsForm)caller).productListTable.Controls[1].Dispose();
                new CustomTable<ProductsForm, ProductDetails>(
                    dbEntities,
                    ((ProductsForm)caller),
                    ((ProductsForm)caller).productListTable,
                    new List<string> { "MODELLO", "SCALA", "USCITA" },
                    dbEntities.products.ToList().Select(x => new Row(x)).ToList(),
                    new List<bool> { true, true, true }
                );
            }
            else if (typeof(T) == typeof(InputForm)) {
                tmp = tmp.TrimStart('C');
                commission commission = dbEntities.commissions.FirstOrDefault(x => x.id.ToString().Equals(tmp));

                int existingCalibrations = dbEntities.calibrations.Where(x => x.commission.id == commission.id).Where(x => x.tests.Any()).Count();
                if (existingCalibrations > 0) {
                    DialogResult dr = MessageBox.Show("Sono state già eseguite alcune calibrazioni associate a questa commessa. Pocedendo con la sua eliminazione verranno persi tutti i dati ad essa associati. Si desidera procedere comunque?", "ATTENZIONE", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
                    if (dr != DialogResult.Yes) return;
                }
                else {
                    DialogResult dr = MessageBox.Show("Sicuro di voler eliminare questa commessa?", "ATTENZIONE", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
                    if (dr != DialogResult.Yes) return;
                }

                dbEntities.commissions.Remove(commission);
                dbEntities.SaveChanges();

                MessageBox.Show("Commessa eliminata con successo.", "SUCCESSO", MessageBoxButtons.OK, MessageBoxIcon.Information);

                ((InputForm)caller).orderListTable.Controls[1].Dispose();
                var list = dbEntities.commissions.ToList();
                new CustomTable<InputForm, CommissionDetailsForm>(
                    dbEntities,
                    ((InputForm)caller),
                    ((InputForm)caller).orderListTable,
                    new List<string> { "ID", "ORDINE", "CLIENTE", "MODELLO", "ESEGUITE" },
                    list.Select(i => new Row(dbEntities, i)).ToList(),
                    new List<bool> { true, false, true }
                );
            }
        }
    }

    private void ActionRow(object sender, EventArgs _, TableLayoutPanel parent) {
        // [0] => riga
        // [1] => azione
        string[] information = ((Button)sender).Name.Split('-');
        
        switch (Convert.ToInt32(information[1])) {
            case 0:
                ShowDetails(RowValuesByIndex(parent, Convert.ToInt32(information[0])));
                break;
            case 1:
                ModifyDetails(RowValuesByIndex(parent, Convert.ToInt32(information[0])));
                break;
            case 2:
                RemoveRow(RowValuesByIndex(parent, Convert.ToInt32(information[0])));
                break;
            default:
                break;
        }
    }

    private List<string> RowValuesByIndex(TableLayoutPanel panel, int index) {
        List<string> data = new List<string>();
        for (int i = 0; i < panel.RowCount; i++) {
            for (int j = 0; j < panel.ColumnCount; j++) {
                if (i == index) {
                    data.Add(panel.GetControlFromPosition(j, i).Text);
                }
            }
        }

        return data;
    }
}

标签: c#.netwinforms

解决方案


每次单击以修改项目时,都会为 saveButton.Click 和 undoButton.Clock 事件添加事件处理程序。

 form.undoButton.Click += UndoModify;
 form.saveButton.Click += SaveChange;

这些事件永远不会被删除。要解决此问题,您应该在修改新表单时从所有其他表单中删除这些事件。

例如,您可以在 saveChange 方法结束时执行此操作。

form.saveButton.Click -= SaveChange;

推荐阅读